查找日期之间的差距和重叠
Find a gap and overlap between dates
我正在构建一份报告,该报告将捕捉负责任的开始日期和结束日期中的所有差距和重叠。
想法是有一个列(状态),它将有 5 个输出(我知道,一条记录可能有多个场景,但我需要按以下顺序分配它们:
- No Responsible - 当根本没有关联的 Responsible(ResponsibleId 或 ResponsibleName 为 NULL)
- 无当前负责人 - 当跨所有与客户关联的记录时,ResponsibleEndDate 不为 NULL(表示当前)。
- Overlap - 当前一个负责人的 ResponsibleEndDate 与下一个负责人的 ResponsibleStartDate 重叠时。
- Gap - 当上一个负责人的 ResponsibleEndDate 和下一个负责人的 ResponsibleStartDate 之间存在差距时。
- 有效 - 当前任负责人的 ResponsibleEndDate 与后任负责人的 ResponsibleStartDate 相差 1 天时。
CREATE TABLE example
(ClientId INT, ClientName VARCHAR(100), ResponsibleId INT, ResponsibleName VARCHAR(100), ResponsibleStartDate DATE, ResponsibleEndDate DATE);
INSERT INTO example
VALUES
(123, 'John Smith', NULL, NULL, NULL, NULL),
(234, 'Thomas Anderson', 12345, 'Tom Cruise', '2019-04-13', '2020-09-15'),
(234, 'Thomas Anderson', 23456, 'John Travolta', '2020-09-16', '2022-01-15'),
(234, 'Thomas Anderson', 37890, 'Van Damm', '2022-01-16', NULL),
(345, 'Mary Tron', NULL, NULL, NULL, NULL),
(456, 'Jackie Chan', 56789, 'Leo Messi', '2018-05-18', '2022-01-18'),
(567, 'Cristiano Ronaldo', 12345, 'Tom Cruise', '2019-05-28', '2021-08-20'),
(567, 'Cristiano Ronaldo', 37890, 'Van Damm', '2021-07-15', '2022-01-15'),
(567, 'Cristiano Ronaldo', 17956, 'Harry Potter', '2022-01-25', NULL)
SELECT * FROM example
我需要的输出:
ClientId
ClientName
ResponsibleId
ResponsibleName
ResponsibleStartDate
ResponsibleEndDate
Status
123
John Smith
NULL
NULL
NULL
NULL
No Responsible
234
Thomas Anderson
12345
Tom Cruise
2019-04-13
2020-09-15
Valid
234
Thomas Anderson
23456
John Travolta
2020-09-16
2022-01-15
Valid
234
Thomas Anderson
37890
Van Damm
2022-01-16
NULL
Valid
345
Mary Tron
NULL
NULL
NULL
NULL
No Responsible
456
Jackie Chan
56789
Leo Messi
2018-05-18
2022-01-18
No Current Responsible
567
Cristiano Ronaldo
12345
Tom Cruise
2019-05-28
2021-08-20
Overlap
567
Cristiano Ronaldo
37890
Van Damm
2021-07-15
2022-01-15
Gap
567
Cristiano Ronaldo
17956
Harry Potter
2022-01-25
NULL
Gap
我能达到的条件只有第一个:
SELECT *,
CASE
WHEN ResponsibleId IS NULL THEN 'No Responsible'
END AS [Status]
FROM example
这是一个好的开始:
declare @example table
(ClientId INT, ClientName VARCHAR(100), ResponsibleId INT, ResponsibleName VARCHAR(100), ResponsibleStartDate DATE, ResponsibleEndDate DATE);
INSERT INTO @example
VALUES
(123, 'John Smith', NULL, NULL, NULL, NULL),
(234, 'Thomas Anderson', 12345, 'Tom Cruise', '2019-04-13', '2020-09-15'),
(234, 'Thomas Anderson', 23456, 'John Travolta', '2020-09-16', '2022-01-15'),
(234, 'Thomas Anderson', 37890, 'Van Damm', '2022-01-16', NULL),
(345, 'Mary Tron', NULL, NULL, NULL, NULL),
(456, 'Jackie Chan', 56789, 'Leo Messi', '2018-05-18', '2022-01-18'),
(567, 'Cristiano Ronaldo', 12345, 'Tom Cruise', '2019-05-28', '2021-08-20'),
(567, 'Cristiano Ronaldo', 37890, 'Van Damm', '2021-07-15', '2022-01-15'),
(567, 'Cristiano Ronaldo', 17956, 'Harry Potter', '2022-01-25', NULL)
;WITH CTE AS
(
SELECT *,
--ROW_NUMBER() OVER(PARTITION BY ClientName ORDER BY COALESCE(ResponsibleStartDate, ResponsibleEndDate)) DN,
LEAD(ResponsibleStartDate)OVER(PARTITION BY ClientName ORDER BY COALESCE(ResponsibleStartDate, ResponsibleEndDate)) NEXT_START_DATE,
LAG(ResponsibleEndDate)OVER(PARTITION BY ClientName ORDER BY COALESCE(ResponsibleStartDate, ResponsibleEndDate)) PREV_END_DATE
FROM @example
)
select *,
CASE
WHEN ResponsibleName IS NULL THEN 'No Responsible'
WHEN PREV_END_DATE IS NOT NULL AND ResponsibleStartDate < PREV_END_DATE then 'OVERLAP'
WHEN PREV_END_DATE IS NOT NULL AND DATEDIFF(dd,PREV_END_DATE, ResponsibleStartDate) = 1 then 'VALID'
WHEN PREV_END_DATE IS NULL then 'VALID'
WHEN PREV_END_DATE IS NOT NULL AND ResponsibleStartDate > PREV_END_DATE then 'GAP'
ELSE 'CASE'
end [STATUS]
from
CTE;
我正在构建一份报告,该报告将捕捉负责任的开始日期和结束日期中的所有差距和重叠。
想法是有一个列(状态),它将有 5 个输出(我知道,一条记录可能有多个场景,但我需要按以下顺序分配它们:
- No Responsible - 当根本没有关联的 Responsible(ResponsibleId 或 ResponsibleName 为 NULL)
- 无当前负责人 - 当跨所有与客户关联的记录时,ResponsibleEndDate 不为 NULL(表示当前)。
- Overlap - 当前一个负责人的 ResponsibleEndDate 与下一个负责人的 ResponsibleStartDate 重叠时。
- Gap - 当上一个负责人的 ResponsibleEndDate 和下一个负责人的 ResponsibleStartDate 之间存在差距时。
- 有效 - 当前任负责人的 ResponsibleEndDate 与后任负责人的 ResponsibleStartDate 相差 1 天时。
CREATE TABLE example
(ClientId INT, ClientName VARCHAR(100), ResponsibleId INT, ResponsibleName VARCHAR(100), ResponsibleStartDate DATE, ResponsibleEndDate DATE);
INSERT INTO example
VALUES
(123, 'John Smith', NULL, NULL, NULL, NULL),
(234, 'Thomas Anderson', 12345, 'Tom Cruise', '2019-04-13', '2020-09-15'),
(234, 'Thomas Anderson', 23456, 'John Travolta', '2020-09-16', '2022-01-15'),
(234, 'Thomas Anderson', 37890, 'Van Damm', '2022-01-16', NULL),
(345, 'Mary Tron', NULL, NULL, NULL, NULL),
(456, 'Jackie Chan', 56789, 'Leo Messi', '2018-05-18', '2022-01-18'),
(567, 'Cristiano Ronaldo', 12345, 'Tom Cruise', '2019-05-28', '2021-08-20'),
(567, 'Cristiano Ronaldo', 37890, 'Van Damm', '2021-07-15', '2022-01-15'),
(567, 'Cristiano Ronaldo', 17956, 'Harry Potter', '2022-01-25', NULL)
SELECT * FROM example
我需要的输出:
ClientId | ClientName | ResponsibleId | ResponsibleName | ResponsibleStartDate | ResponsibleEndDate | Status |
---|---|---|---|---|---|---|
123 | John Smith | NULL | NULL | NULL | NULL | No Responsible |
234 | Thomas Anderson | 12345 | Tom Cruise | 2019-04-13 | 2020-09-15 | Valid |
234 | Thomas Anderson | 23456 | John Travolta | 2020-09-16 | 2022-01-15 | Valid |
234 | Thomas Anderson | 37890 | Van Damm | 2022-01-16 | NULL | Valid |
345 | Mary Tron | NULL | NULL | NULL | NULL | No Responsible |
456 | Jackie Chan | 56789 | Leo Messi | 2018-05-18 | 2022-01-18 | No Current Responsible |
567 | Cristiano Ronaldo | 12345 | Tom Cruise | 2019-05-28 | 2021-08-20 | Overlap |
567 | Cristiano Ronaldo | 37890 | Van Damm | 2021-07-15 | 2022-01-15 | Gap |
567 | Cristiano Ronaldo | 17956 | Harry Potter | 2022-01-25 | NULL | Gap |
我能达到的条件只有第一个:
SELECT *,
CASE
WHEN ResponsibleId IS NULL THEN 'No Responsible'
END AS [Status]
FROM example
这是一个好的开始:
declare @example table
(ClientId INT, ClientName VARCHAR(100), ResponsibleId INT, ResponsibleName VARCHAR(100), ResponsibleStartDate DATE, ResponsibleEndDate DATE);
INSERT INTO @example
VALUES
(123, 'John Smith', NULL, NULL, NULL, NULL),
(234, 'Thomas Anderson', 12345, 'Tom Cruise', '2019-04-13', '2020-09-15'),
(234, 'Thomas Anderson', 23456, 'John Travolta', '2020-09-16', '2022-01-15'),
(234, 'Thomas Anderson', 37890, 'Van Damm', '2022-01-16', NULL),
(345, 'Mary Tron', NULL, NULL, NULL, NULL),
(456, 'Jackie Chan', 56789, 'Leo Messi', '2018-05-18', '2022-01-18'),
(567, 'Cristiano Ronaldo', 12345, 'Tom Cruise', '2019-05-28', '2021-08-20'),
(567, 'Cristiano Ronaldo', 37890, 'Van Damm', '2021-07-15', '2022-01-15'),
(567, 'Cristiano Ronaldo', 17956, 'Harry Potter', '2022-01-25', NULL)
;WITH CTE AS
(
SELECT *,
--ROW_NUMBER() OVER(PARTITION BY ClientName ORDER BY COALESCE(ResponsibleStartDate, ResponsibleEndDate)) DN,
LEAD(ResponsibleStartDate)OVER(PARTITION BY ClientName ORDER BY COALESCE(ResponsibleStartDate, ResponsibleEndDate)) NEXT_START_DATE,
LAG(ResponsibleEndDate)OVER(PARTITION BY ClientName ORDER BY COALESCE(ResponsibleStartDate, ResponsibleEndDate)) PREV_END_DATE
FROM @example
)
select *,
CASE
WHEN ResponsibleName IS NULL THEN 'No Responsible'
WHEN PREV_END_DATE IS NOT NULL AND ResponsibleStartDate < PREV_END_DATE then 'OVERLAP'
WHEN PREV_END_DATE IS NOT NULL AND DATEDIFF(dd,PREV_END_DATE, ResponsibleStartDate) = 1 then 'VALID'
WHEN PREV_END_DATE IS NULL then 'VALID'
WHEN PREV_END_DATE IS NOT NULL AND ResponsibleStartDate > PREV_END_DATE then 'GAP'
ELSE 'CASE'
end [STATUS]
from
CTE;