两列上的 DENSE_RANK,其中一列是不同的值,另一列是重复的
Posted
技术标签:
【中文标题】两列上的 DENSE_RANK,其中一列是不同的值,另一列是重复的【英文标题】:DENSE_RANK on two columns, where one column are distinct values and the other has duplicate 【发布时间】:2021-10-23 20:48:14 【问题描述】:在以下情况下,我很难理解如何应用 DENSE_RANK()
来获得我想要的结果:
ID | Date | Value |
---|---|---|
1 | 1990-05-17 | 1.00 |
1 | 1991-10-12 | 1.00 |
1 | 1992-08-01 | 1.00 |
1 | 1993-07-05 | 0.67 |
1 | 1994-05-02 | 0.67 |
1 | 1995-02-01 | 1.00 |
1 | 1996-03-01 | 1.00 |
基于上述数据,我尝试使用Date
和Value
列的组合来识别不同的时期,其中一个独特的时期是从Value
列从一个值更改为另一个值的位置确定的.这是我正在寻找的结果:
ID | Date | Value | Period |
---|---|---|---|
1 | 1990-05-17 | 1.00 | 1 |
1 | 1991-10-12 | 1.00 | 1 |
1 | 1992-08-01 | 1.00 | 1 |
1 | 1993-07-05 | 0.67 | 2 |
1 | 1994-05-02 | 0.67 | 2 |
1 | 1995-02-01 | 1.00 | 3 |
1 | 1996-03-01 | 1.00 | 3 |
如您所见,有 3 个不同的时期。我遇到的问题是,当我使用DENSE_RANK()
时,我会得到以下两种结果之一:
SELECT DENSE_RANK() OVER (PARTITION BY ID ORDER BY Date, Value)
ID | Date | Value | Period |
---|---|---|---|
1 | 1990-05-17 | 1.00 | 1 |
1 | 1991-10-12 | 1.00 | 2 |
1 | 1992-08-01 | 1.00 | 3 |
1 | 1993-07-05 | 0.67 | 4 |
1 | 1994-05-02 | 0.67 | 5 |
1 | 1995-02-01 | 1.00 | 6 |
1 | 1996-03-01 | 1.00 | 7 |
SELECT DENSE_RANK() OVER (PARTITION BY ID ORDER BY Value)
ID | Date | Value | Period |
---|---|---|---|
1 | 1990-05-17 | 1.00 | 1 |
1 | 1991-10-12 | 1.00 | 1 |
1 | 1992-08-01 | 1.00 | 1 |
1 | 1993-07-05 | 0.67 | 2 |
1 | 1994-05-02 | 0.67 | 2 |
1 | 1995-02-01 | 1.00 | 1 |
1 | 1996-03-01 | 1.00 | 1 |
如您所见,问题在于Date
列,因为我需要将其作为累积期。此外,句号的数量从ID
到ID
不等,Date
列背后没有一致的科学依据。例如,一个成员在一年内可能有两个条目。
【问题讨论】:
【参考方案1】:您可以使用LAG()
窗口函数为每一行获取其先前的值,并使用SUM()
窗口函数进行条件聚合获取Periods
:
SELECT ID, Date, Value,
SUM(CASE WHEN VALUE = prev_value THEN 0 ELSE 1 END) OVER (PARTITION BY ID ORDER BY Date) Period
FROM (
SELECT *, LAG(Value) OVER (PARTITION BY ID ORDER BY Date) prev_value
FROM tablename
) t
ORDER BY Date;
请参阅demo。
【讨论】:
【参考方案2】:这被称为间隙和孤岛问题。一种方法是使用几个ROW_NUMBER
s 将您的数据分组:
WITH CTE AS(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY [date],[value])-
ROW_NUMBER() OVER (PARTITION BY ID, [value] ORDER BY [date]) AS Grp
FROM (VALUES(1,CONVERT(date,'1990-05-17'),1.00),
(1,CONVERT(date,'1991-10-12'),1.00),
(1,CONVERT(date,'1992-08-01'),1.00),
(1,CONVERT(date,'1993-07-05'),0.67),
(1,CONVERT(date,'1994-05-02'),0.67),
(1,CONVERT(date,'1995-02-01'),1.00),
(1,CONVERT(date,'1996-03-01'),1.00))V(ID,Date,Value))
SELECT ID,
Date,
Value,
DENSE_RANK() OVER (PARTITION BY ID ORDER BY Grp) AS Period
FROM CTE;
【讨论】:
以上是关于两列上的 DENSE_RANK,其中一列是不同的值,另一列是重复的的主要内容,如果未能解决你的问题,请参考以下文章