SQL查询:如何筛选CODE为13/14且日期覆盖整月的人员记录
需求背景
需要编写SQL实现如下筛选逻辑:
- 筛选出CODE取值仅为13或14的IDNR
- 该IDNR下所有记录的START-DATE到END-DATE区间可以连续覆盖2021年1月全月(2021-01-01至2021-01-31)
- 返回符合要求的IDNR对应的全部记录
样例说明
现有原始样例数据:
| IDNR | CODE | START-DATE | END-DATE |
|---|---|---|---|
| 16 | 13 | 2021-01-07 | 2021-01-21 |
| 16 | 13 | 2021-01-22 | 2021-01-31 |
| 17 | 13 | 2021-01-01 | 2021-01-01 |
| 17 | 12 | 2021-01-02 | 2021-01-14 |
| 17 | 14 | 2021-01-15 | 2021-01-31 |
| 18 | 14 | 2021-01-01 | 2021-01-19 |
| 18 | 13 | 2021-01-20 | 2021-01-29 |
| 18 | 14 | 2021-01-30 | 2021-01-31 |
期望输出结果仅保留IDNR为16和18的所有记录,其中IDNR=17因存在CODE=12的记录直接被排除。
实现逻辑
- 先排除所有存在非13/14 CODE值的IDNR
- 对剩余IDNR的所有日期间隙做校验,判断区间是否完整覆盖2021-01-01至2021-01-31且无断层
- 拉取符合条件的IDNR的全部原始记录
参考SQL代码(兼容大部分主流数据库语法)
WITH valid_idnr AS ( -- 第一步:筛选仅包含CODE为13/14的IDNR SELECT IDNR FROM your_table_name GROUP BY IDNR HAVING COUNT(CASE WHEN CODE NOT IN (13,14) THEN 1 END) = 0 ), date_range_aggr AS ( -- 第二步:判断IDNR的日期区间是否覆盖1月全月且无间隙 SELECT t.IDNR FROM your_table_name t INNER JOIN valid_idnr vi ON t.IDNR = vi.IDNR -- 仅筛选和1月有交集的区间 WHERE t.START_DATE <= DATE '2021-01-31' AND t.END_DATE >= DATE '2021-01-01' GROUP BY t.IDNR HAVING MIN(t.START_DATE) <= DATE '2021-01-01' AND MAX(t.END_DATE) >= DATE '2021-01-31' -- 校验1月范围内不存在日期间隙 AND NOT EXISTS ( SELECT 1 FROM ( SELECT END_DATE + INTERVAL '1 day' AS gap_day FROM your_table_name t1 WHERE t1.IDNR = t.IDNR AND t1.END_DATE BETWEEN DATE '2021-01-01' AND DATE '2021-01-30' ) gaps WHERE NOT EXISTS ( SELECT 1 FROM your_table_name t2 WHERE t2.IDNR = t.IDNR AND gaps.gap_day BETWEEN t2.START_DATE AND t2.END_DATE ) ) ) -- 第三步:拉取符合条件的IDNR的全部记录 SELECT t.* FROM your_table_name t INNER JOIN date_range_aggr dra ON t.IDNR = dra.IDNR ORDER BY t.IDNR, t.START_DATE;
注:不同数据库日期运算语法存在差异,可对应调整
INTERVAL '1 day'写法,例如MySQL中可替换为DATE_ADD(t1.END_DATE, INTERVAL 1 DAY)。
内容的提问来源于stack exchange,提问作者Tick _Tack
相关产品推荐
相关产品推荐

