如何比较给定数据集的最新两个值

How to compare the latest two values for a given set of data

我需要一个查询,为每个在 MAX(PublishDate)上出版一本书的作者提供最新的作者、出版商和书籍,并比较每个作者最近 2 本书的出版商,看看它是否有变了。它不必是单个语句,但不能创建任何物理表。

declare @books TABLE(Author nvarchar(30), PublishDate datetime2(3), Publisher nvarchar(30), Title nvarchar(30))

INSERT INTO @books
VALUES  ('Author A', '15 June 2017 15:47', 'Publisher A', 'Book 1'),
        ('Author A', '15 May 2016 14:47', 'Publisher B', 'Book 2'),
        ('Author B', '15 May 2016 14:47', 'Publisher C', 'Book 3'),
        ('Author B', '15 April 2015 13:47', 'Publisher D', 'Book 4'),
        ('Author C', '15 June 2017 15:47', 'Publisher E', 'Book 5'),
        ('Author C', '15 May 2014 14:47', 'Publisher E', 'Book 6'),
        ('Author D', '15 June 2017 15:47', 'Publisher F', 'Book 7'),
        ('Author D', '15 May 2013 14:47', 'Publisher F', 'Book 8'),
        ('Author E', '15 June 2017 15:47', 'Publisher G', 'Book 9'),
        ('Author E', '15 May 2012 14:47', 'Publisher H', 'Book 10'),
        ('Author E', '15 April 2011 13:47', 'Publisher I', 'Book 11')


Output:  
Author         Publisher          PublisherChanged          Book
Author A       Publisher A        1                         Book 1
Author C       Publisher E        0                         Book 5
Author D       Publisher F        0                         Book 7
Author E       Publisher G        1                         Book 9

2008 R2

你必须在它自己上创建一个关系,我在这里使用 row_number() 基本上将 table 连接到它自己上。如果它很大 table,您可能想使用临时 table 而不是 cte。我将排名第 1 的发布者与排名第 2 的发布者进行比较:

declare @books table (Author nvarchar(30), PublishDate datetime2(3), Publisher nvarchar(30), Title nvarchar(30))

insert into @books
values  ('Author A', '15 June 2017 15:47', 'Publisher A', 'Book 1'),
        ('Author A', '15 May 2016 14:47', 'Publisher B', 'Book 2'),
        ('Author B', '15 May 2016 14:47', 'Publisher C', 'Book 3'),
        ('Author B', '15 April 2015 13:47', 'Publisher D', 'Book 4'),
        ('Author C', '15 June 2017 15:47', 'Publisher E', 'Book 5'),
        ('Author C', '15 May 2014 14:47', 'Publisher E', 'Book 6'),
        ('Author D', '15 June 2017 15:47', 'Publisher F', 'Book 7'),
        ('Author D', '15 May 2013 14:47', 'Publisher F', 'Book 8'),
        ('Author E', '15 June 2017 15:47', 'Publisher G', 'Book 9'),
        ('Author E', '15 May 2012 14:47', 'Publisher H', 'Book 10'),
        ('Author E', '15 April 2011 13:47', 'Publisher I', 'Book 11');

declare @max_date date = (
        select max(PublishDate)
        from @books
        );

with EvaluateChanges (
    Author
    ,PublishDate
    ,Publisher
    ,Title
    ,DateRanking
    )
as (
    select Author
        ,PublishDate
        ,Publisher
        ,Title
        ,row_number() over (partition by Author order by PublishDate desc)
    from @books
    )
select e1.Author
    ,e1.Publisher
    ,case when isnull(e2.Publisher, e1.Publisher) <> e1.Publisher then 1 else 0 end as PublisherChanged
    ,e1.Title
from EvaluateChanges as e1
left join EvaluateChanges as e2
    on e1.Author = e2.Author
        and e2.DateRanking = 2
where cast(e1.PublishDate as date) = @max_date
    and e1.DateRanking = 1;

2012 年以后

这是 2012 年的解决方案。我使用 2012 年引入的 lead() 函数帮助这里分析作者的上一行。 isnull 的原因是当分区中没有要比较的前一行时,lead()null。当它是 null 时,我通过为当前行上下文分配与 Publisher 相同的值来告诉评估假设没有变化。我正在为您的最大日期使用日期变量 cast 因为您的字段是 datetime.

declare @books table (Author nvarchar(30), PublishDate datetime2(3), Publisher nvarchar(30), Title nvarchar(30))

insert into @books
values  ('Author A', '15 June 2017 15:47', 'Publisher A', 'Book 1'),
        ('Author A', '15 May 2016 14:47', 'Publisher B', 'Book 2'),
        ('Author B', '15 May 2016 14:47', 'Publisher C', 'Book 3'),
        ('Author B', '15 April 2015 13:47', 'Publisher D', 'Book 4'),
        ('Author C', '15 June 2017 15:47', 'Publisher E', 'Book 5'),
        ('Author C', '15 May 2014 14:47', 'Publisher E', 'Book 6'),
        ('Author D', '15 June 2017 15:47', 'Publisher F', 'Book 7'),
        ('Author D', '15 May 2013 14:47', 'Publisher F', 'Book 8'),
        ('Author E', '15 June 2017 15:47', 'Publisher G', 'Book 9'),
        ('Author E', '15 May 2012 14:47', 'Publisher H', 'Book 10'),
        ('Author E', '15 April 2011 13:47', 'Publisher I', 'Book 11');

declare @max_date date = (
        select max(PublishDate)
        from @books
        );

with EvaluateChanges (
    Author
    ,PublishDate
    ,Publisher
    ,Title
    ,PublisherChanged
    )
as (
    select Author
        ,PublishDate
        ,Publisher
        ,Title
        ,case 
            when isnull(lead(Publisher) over (
                        partition by author order by PublishDate desc
                        ), Publisher) <> Publisher
                then 1
            else 0
            end
    from @books
    )
select Author
    ,Publisher
    ,PublisherChanged
    ,Title
from EvaluateChanges
where cast(PublishDate as date) = @max_date;

更多关于 lead() 及其堂兄 lag() 的阅读:

https://docs.microsoft.com/en-us/sql/t-sql/functions/lead-transact-sql?view=sql-server-2017 https://docs.microsoft.com/en-us/sql/t-sql/functions/lag-transact-sql?view=sql-server-2017