我们有以下架构:
CREATE TABLE enrollments (
case_id INT,
enrollment_id VARCHAR(10),
open_date DATE,
closed_date DATE,
status VARCHAR(10)
);
假设记录是:
INSERT INTO enrollments (case_id, enrollment_id, open_date, closed_date, status)
VALUES
(1, 'ab', '2024-10-01', '2024-10-05', 'closed'),
(1, 'bc', '2024-10-03', '2024-10-04', 'closed'),
(1, 'bd', '2024-10-05', '2024-10-15', 'closed'),
(1, 'sx', '2024-10-12', '2024-10-19', 'closed'),
(1, 'za', '2024-10-16', '2024-10-21', 'closed'),
(1, 'ca', '2024-10-25', '2024-10-26', 'closed'),
(1, 'dd', '2024-10-25', '2024-10-27', 'closed'),
(1, 'kh', '2024-10-28', NULL, 'open'),
(1, 'kk', '2024-10-28', NULL, 'open');
我只想要记录
仅考虑与之前注册不重叠的 CPE,即当前注册的开放日期不应介于之前注册的开放日期和关闭日期之间。
如果两次注册在同一开放日期开始,请考虑长期注册,即最近的关闭日期。
如果我们有两个开放注册,且开放日期不重叠,请考虑两者。
仅使用之前的有效注册来验证当前注册,这意味着记录“za”注册与之前的有效注册不重叠,那么我们需要考虑该记录,即使它与“sx”记录重叠,因为“sx”是一个无效的 cpe,因为它重叠。
所以我需要这个输出:
案例_id | 注册_id | 开放日期 | 关闭日期 | 状态 |
---|---|---|---|---|
1 | ab | 2024年10月1日 | 2024年5月10日 | 已关闭 |
1 | BD | 2024年5月10日 | 2024年10月15日 | 已关闭 |
1 | za | 2024年10月16日 | 2024年10月21日 | 已关闭 |
1 | dd | 2024年10月25日 | 2024年10月27日 | 已关闭 |
1 | kh | 2024年10月28日 | 空 | 打开 |
1 | kk | 2024年10月28日 | 空 | 打开 |
我该怎么做?
一种选择是创建一个 cte(网格),将不同的日期异常标记为“重叠”、“长”、“打开”或“空”。在主 sql 中,使用 Case 表达式中的 flag 列为感兴趣的行定义 open_date 列,或为要排除的行定义 Null。
报名表样本
案例_id | 注册_id | 开放日期 | 关闭日期 | 状态 |
---|---|---|---|---|
1 | ab | 2024-10-01 | 2024-10-05 | 已关闭 |
1 | BC | 2024-10-03 | 2024-10-04 | 已关闭 |
1 | BD | 2024-10-05 | 2024-10-15 | 已关闭 |
1 | sx | 2024-10-12 | 2024-10-19 | 已关闭 |
1 | za | 2024-10-16 | 2024-10-21 | 已关闭 |
1 | ca | 2024-10-25 | 2024-10-26 | 已关闭 |
1 | dd | 2024-10-25 | 2024-10-27 | 已关闭 |
1 | kh | 2024-10-28 | 空 | 打开 |
1 | kk | 2024-10-28 | 空 | 打开 |
-- flag different cases
WITH
grid AS
( Select g.*, Case When ( g.open_date = g.prev_open Or g.open_date = g.next_open ) And g.status = 'closed'
Then 'Long'
When ( g.open_date = g.prev_open Or g.open_date = g.next_open )
Then 'Opened'
When g.open_date < g.prev_close
Then 'Overlap'
End as flag
From ( Select e.*,
LAG(e.open_date) Over(Partition By e.case_id Order By e.open_date) as prev_open,
LAG(e.closed_date) Over(Partition By e.case_id Order By e.open_date) as prev_close,
LEAD(e.open_date) Over(Partition By e.case_id Order By e.open_date) as next_open
From enrollments e
Order By e.case_id, e.open_date
) g
Order By g.case_id, g.open_date
)
-- M a i n S Q L :
SELECT x.*
FROM
( Select case_id, enrollment_id,
Case When flag Is Null
Then open_date
When flag = 'Overlap' And
open_date < Max(Case When flag Is Null Then closed_date End)
Over(Partition By case_id Order By open_date
Rows Between Unbounded Preceding And 1 Preceding)
Then Null
When flag = 'Overlap' And
open_date > Max(Case When flag Is Null Then closed_date End)
Over(Partition By case_id Order By open_date
Rows Between Unbounded Preceding And 1 Preceding)
Then open_date
When flag = 'Long' And
open_date = next_open
Then Null
When flag = 'Long' And
open_date != next_open
Then open_date
Else open_date
End as new_open_date,
closed_date,
status
From grid
Order By case_id, new_open_date
) x
WHERE x.new_open_date Is Not Null
结果:
案例_id | 注册_id | 新开放日期 | 关闭日期 | 状态 |
---|---|---|---|---|
1 | ab | 2024-10-01 | 2024-10-05 | 已关闭 |
1 | BD | 2024-10-05 | 2024-10-15 | 已关闭 |
1 | za | 2024-10-16 | 2024-10-21 | 已关闭 |
1 | dd | 2024-10-25 | 2024-10-27 | 已关闭 |
1 | kh | 2024-10-28 | 空 | 打开 |
1 | kk | 2024-10-28 | 空 | 打开 |