SQL 按列更改时间排名

SQL Ranking by when a column changes

我正在解决 SQL 中的一个问题,我试图根据列的更改时间对其进行排名。

目前的 table 基本上是这样的:

DATE        STATUS
10/18/10    A        
10/16/10    A        
10/14/10    B        
10/12/10    A        

我想根据日期列对状态列进行适当的排名,但仅当状态列发生变化时。例如:

 DATE        STATUS   RANK 
 10/18/10    A        1 
 10/16/10    A        1 
 10/14/10    B        2 
 10/12/10    A        3 
 10/10/10    A        3

关于如何解决这个问题有什么想法吗?我玩过 RANK() 和 DENSE_RANK() 并且无法获得我想要的输出。谢谢

有几种方法可以做到这一点。一种简单的方法是使用子查询简单地计算与当前值不同的值的数量。另一种方法是使用行号的差异。两者都提供了一个组标识符,然后您需要更加努力地工作才能获得您想要的排名:

select t.date, t.status, dense_rank() over (order by mindate) as ranking
from (select t.*, min(date) over (partition by grp, status) as mindate   
      from (select t.*,
                   (row_number() over (order by date) -
                    row_number() over (partition by status order by date)
                   ) as grp
            from table t
           ) t
     ) t;

根据顺序,您可能需要在外部查询中使用 order by mindate desc

DB2 是支持 LAGLEAD OLAP windowing 函数的 SQL DBMS 之一,这使得比较当前表达式中的表达式成为可能行与同一分区中的其他行 window。 RANKDENSE_RANK 都不完全适合您想要的计算(状态更改的 运行 计数),但是可以使用 SUM 和二进制表达式来完成:

WITH StatusHistory( histDate, statusCode ) AS (
    VALUES 
    ( DATE( '2010-10-10' ), 'A' ), 
    ( DATE( '2010-10-12' ), 'A' ),
    ( DATE( '2010-10-14' ), 'B' ), 
    ( DATE( '2010-10-16' ), 'A' ),
    ( DATE( '2010-10-18' ), 'A' )
)
SELECT histDate, 
statusCode, 
SMALLINT( 
    SUM( 
        CASE LAG( statusCode, 1 ) 
           OVER ( ORDER BY histDate DESC) 
        WHEN statusCode 
        THEN 0 
        ELSE 1
        END
    ) OVER ( ORDER BY histDate DESC )
) AS changeSeq
FROM StatusHistory
ORDER BY histDate DESC
;

HISTDATE   STATUSCODE CHANGESEQ
---------- ---------- ---------
10/18/2010 A                  1
10/16/2010 A                  1
10/14/2010 B                  2
10/12/2010 A                  3
10/10/2010 A                  3

5 record(s) selected.