Reputation: 411
I have the below data sample with a ROW_NUMBER function which has previously done the job for us.
+----+-------------------------+------+--------+------+-----+
| ID | Start_Date | Code | Serial | Type | Sqn |
+----+-------------------------+------+--------+------+-----+
| 03 | 2020-09-23 00:00:00.000 | 674 | 4388 | P | 1 |
| 03 | 2020-09-24 00:00:00.000 | 654 | 4388 | T | 1 |
| 03 | 2020-09-24 00:00:00.000 | 912 | 4388 | T | 2 |
| 42 | 2019-08-23 00:00:00.000 | 671 | 1316 | P | 1 |
| 42 | 2019-08-23 00:00:00.000 | 921 | 1316 | P | 2 |
| 42 | 2019-08-27 00:00:00.000 | 671 | 1316 | P | 1 |
| 42 | 2019-08-29 00:00:00.000 | 671 | 1316 | P | 1 |
| 42 | 2019-08-29 00:00:00.000 | 921 | 1316 | P | 2 |
| 42 | 2019-08-29 00:00:00.000 | 654 | 1316 | T | 3 |
| 42 | 2019-08-29 00:00:00.000 | 911 | 1316 | T | 4 |
| 51 | 2020-09-22 00:00:00.000 | 674 | 3210 | P | 1 |
| 51 | 2020-09-22 00:00:00.000 | 654 | 3210 | T | 2 |
| 51 | 2020-09-22 00:00:00.000 | 912 | 3210 | T | 3 |
+----+-------------------------+------+--------+------+-----+
ROW_NUMBER () OVER (PARTITION BY Serial,[Start_Date] ORDER BY Type, Sqn) AS Sqn
However, due to a process change we need to handle certain records (674 + P on days prior) to get partitioned together, without affecting the others.
i.e. as below
+----+-------------------------+------+--------+------+-----+
| ID | Start_Date | Code | Serial | Type | Sqn |
+----+-------------------------+------+--------+------+-----+
| 03 | 2020-09-23 00:00:00.000 | 674 | 4388 | P | 1 |
| 03 | 2020-09-24 00:00:00.000 | 654 | 4388 | T | 2 |
| 03 | 2020-09-24 00:00:00.000 | 912 | 4388 | T | 3 |
| 42 | 2019-08-23 00:00:00.000 | 671 | 1316 | P | 1 |
| 42 | 2019-08-23 00:00:00.000 | 921 | 1316 | P | 2 |
| 42 | 2019-08-27 00:00:00.000 | 671 | 1316 | P | 1 |
| 42 | 2019-08-29 00:00:00.000 | 671 | 1316 | P | 1 |
| 42 | 2019-08-29 00:00:00.000 | 921 | 1316 | P | 2 |
| 42 | 2019-08-29 00:00:00.000 | 654 | 1316 | T | 3 |
| 42 | 2019-08-29 00:00:00.000 | 911 | 1316 | T | 4 |
| 51 | 2020-09-22 00:00:00.000 | 674 | 3210 | P | 1 |
| 51 | 2020-09-22 00:00:00.000 | 654 | 3210 | T | 2 |
| 51 | 2020-09-22 00:00:00.000 | 912 | 3210 | T | 3 |
+----+-------------------------+------+--------+------+-----+
You can see the ID 03 Sqn is now 1,2,3 instead of 1,1,2.
I had considered adding a CASE WHEN into the ROW_NUMBER function, but couldn't quite crack it.
Upvotes: 0
Views: 60
Reputation: 69749
Instead of partitioning by StartDate, you can modify it slightly to add one day to start day for the criteria you have set out, e.g.
DATEADD(DAY, CASE WHEN t.Type = 'P' AND Code = 674 THEN 1 ELSE 0 END, [Start_Date])
e.g.
DECLARE @T TABLE (ID INT, Start_Date DATETIME, Code INT, Serial INT, Type VARCHAR(1));
INSERT @T (ID, Start_Date, Code, Serial, Type)
VALUES
(03, '2020-09-23 00:00:00', 674, 4388, 'P'),
(03, '2020-09-24 00:00:00', 654, 4388, 'T'),
(03, '2020-09-24 00:00:00', 912, 4388, 'T'),
(42, '2019-08-23 00:00:00', 671, 1316, 'P'),
(42, '2019-08-23 00:00:00', 921, 1316, 'P'),
(42, '2019-08-27 00:00:00', 671, 1316, 'P'),
(42, '2019-08-29 00:00:00', 671, 1316, 'P'),
(42, '2019-08-29 00:00:00', 921, 1316, 'P'),
(42, '2019-08-29 00:00:00', 654, 1316, 'T'),
(42, '2019-08-29 00:00:00', 911, 1316, 'T'),
(51, '2020-09-22 00:00:00', 674, 3210, 'P'),
(51, '2020-09-22 00:00:00', 654, 3210, 'T'),
(51, '2020-09-22 00:00:00', 912, 3210, 'T');
SELECT *,
ROW_NUMBER () OVER (PARTITION BY Serial, DATEADD(DAY, CASE WHEN t.Type = 'P' AND Code = 674 THEN 1 ELSE 0 END, [Start_Date]) ORDER BY Type, Code) AS Sqn
FROM @T AS t
ORDER BY ID
ADENDUM
The following appears to work as required:
SELECT t.ID, t.Code, t.Serial, t.Type, t.Start_Date,
ROW_NUMBER () OVER (PARTITION BY Serial,PartitionDate ORDER BY Type, T.Code)
FROM ( SELECT t.ID,
PartitionDate = CASE WHEN t.Code = 674 AND t.Type = 'P' AND
DATEDIFF(DAY, LEAD(t.Start_Date) OVER(PARTITION BY ID ORDER BY Type, Code), t.Start_Date) <= 1
THEN LEAD(t.Start_Date) OVER(PARTITION BY ID ORDER BY t.Start_Date, Type, Code)
ELSE t.Start_Date
END,
t.Code,
t.Serial,
t.Type,
t.Start_Date
FROM @T AS t
) AS t
ORDER BY ID, t.Start_Date, t.Type
This creates a new date in a subquery to partition by which is just the start_date, unless the code is 674 and the type is T and the next event for that ID is within 1 day (change as required), in which case it will use the next event date for that particular ID.
Upvotes: 1