SQL Server T-SQL CTE ROW_NUMBER() OVER PARTITION 基于一个值
想要基于 NAME、VAL1 和 VAL2 列的数字,然后按 DT 日期降序排列。
WITH cteA (NAME, VAL1, VAL2, DT) AS
(
SELECT 'A', '7100', 'PN1', '2023-03-01' UNION
SELECT 'A', '7100', 'PN1', '2023-01-01' UNION
SELECT 'A', '7100', 'PN3', '2022-09-01' UNION
SELECT 'A', '7100', 'PN1', '2022-05-20' UNION
SELECT 'A', '7100', 'PN1', '2022-05-09' UNION
SELECT 'A', '7100', 'PN1', '2022-08-20'
),
cteB AS
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY NAME, VAL1, VAL2
ORDER BY DT DESC) ROWNUMBER
FROM cteA
)
SELECT *
FROM cteB
ORDER BY DT DESC
使用
ROW_NUMBER OVER PARTITION BY NAME, VAL1
,和VAL2但结果上的数字不符合要求:
姓名 | VAL1 | VAL2 | DT | 行号 |
---|---|---|---|---|
A | 7100 | PN1 | 2023-03-01 | 1 |
A | 7100 | PN1 | 2023-01-01 | 2 |
A | 7100 | PN3 | 2022-09-01 | 1 |
A | 7100 | PN1 | 2022-08-20 | 3 |
A | 7100 | PN1 | 2022-05-20 | 4 |
A | 7100 | PN1 | 2022-05-09 | 5 |
数字需要用 VAL2 列分隔:PN1(PN3 之前的前 2 行),PN3 本身,& PN1(PN3 之后的最后 3 行),
并保持DT下降,
我期待结果中的数字(ROWNUMBER 列)是这样的:
姓名 | VAL1 | VAL2 | DT | 行号 |
---|---|---|---|---|
A | 7100 | PN1 | 2023-03-01 | 1 |
A | 7100 | PN1 | 2023-01-01 | 1 |
A | 7100 | PN3 | 2022-09-01 | 2 |
A | 7100 | PN1 | 2022-08-20 | 3 |
A | 7100 | PN1 | 2022-05-20 | 3 |
A | 7100 | PN1 | 2022-05-09 | 3 |
这是间隙和孤岛问题的变体,您需要一个中间步骤来识别孤岛 (Val2),您可以使用 lag 来标记值何时发生变化,运行总计然后得到您的行号:
with cteA (NAME, VAL1, VAL2, DT) as
(
select 'A', '7100', 'PN1', '2023-03-01' union
select 'A', '7100', 'PN1', '2023-01-01' union
select 'A', '7100', 'PN3', '2022-09-01' union
select 'A', '7100', 'PN1', '2022-05-20' union
select 'A', '7100', 'PN1', '2022-05-09' union
select 'A', '7100', 'PN1', '2022-08-20'
),
cteB as
(
select *,
case when Lag(val2,1,1) over (partition by NAME, VAL1 order by DT desc)
!= val2 then 1
end gp
from cteA
)
select *,
Sum(gp) over(partition by NAME, VAL1 order by DT desc) Rownumber
from cteB
order by DT desc;