重叠和非重叠SQL查询

问题描述 投票:0回答:1

我们有以下架构:

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');

我只想要记录

  1. 仅考虑与之前注册不重叠的 CPE,即当前注册的开放日期不应介于之前注册的开放日期和关闭日期之间。

  2. 如果两次注册在同一开放日期开始,请考虑长期注册,即最近的关闭日期。

  3. 如果我们有两个开放注册,且开放日期不重叠,请考虑两者。

  4. 仅使用之前的有效注册来验证当前注册,这意味着记录“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日 打开

我该怎么做?

sql mysql gaps-and-islands
1个回答
0
投票

一种选择是创建一个 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 打开

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.