SQL Server CTE ROW_NUMBER() OVER PARTITION based on a value

cuxqih21  于 2023-03-22  发布在  其他
关注(0)|答案(1)|浏览(149)

SQL Server T-SQL CTE ROW_NUMBER() OVER PARTITION based on a value

Want numbers based on NAME, VAL1, and VAL2 columns, then order by DT dates descending.

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

Using the ROW_NUMBER OVER PARTITION BY NAME, VAL1 , and VAL2 but the numbers on the results are not as desired:

NAMEVAL1VAL2DTROWNUMBER
A7100PN12023-03-011
A7100PN12023-01-012
A7100PN32022-09-011
A7100PN12022-08-203
A7100PN12022-05-204
A7100PN12022-05-095

The numbers need to be separated by VAL2 column: PN1 (first 2 rows before PN3), PN3 itself, & PN1 (last 3 rows after PN3),

and keep DT descending,

I am expecting numbers (ROWNUMBER column) on the result like this:
| NAME | VAL1 | VAL2 | DT | ROWNUMBER |
| ------------ | ------------ | ------------ | ------------ | ------------ |
| 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 |

guicsvcw

guicsvcw1#

This is a variation of a gaps-and-island problem, you need an intermediary step to identify the islands (Val2) which you can do using lag to mark when the value changes, a running total then gets your row number:

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;

相关问题