You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否用含窗口函数的纯SQL实现日期区间配对转换(无自连接)

问题

现有表T1包含id和event_date列(主键为(id, event_date)),存储的是某流程的起止日期且按顺序排列。需要生成表T2,将T1中第1条记录的日期作为start_date、第2条作为end_date,第3与第4条、第5与第6条等依次配对,直至处理完所有记录。询问是否可通过包含窗口函数的纯SQL语句(无需自连接、存储过程或函数)实现该需求,可考虑使用递归查询(WITH RECURSIVE)。

表结构及测试数据

T1表结构

create table T1
(
id bigint not null,
event_date date not null,
PRIMARY KEY (id, event_date)
)

T1测试数据

insert into T1 VALUES
('354312','2020-03-01'),
('354312','2020-08-01'),
('354312','2020-12-01'),
('354312','2020-06-30'),
('354312','2020-09-30'),
('354312','2020-08-31'),
('354312','2020-10-31'),
('354312','2020-12-31')

目标表T2结构

create table T2
(
id bigint not null primary key,
start_date date not null,
end_date date
)
解决方案

完全可以通过纯SQL结合窗口函数实现,无需自连接、存储过程或函数,也不需要递归查询,用ROW_NUMBER()窗口函数分组配对即可,具体实现如下:

实现SQL

WITH numbered_dates AS (
    SELECT 
        id,
        event_date,
        ROW_NUMBER() OVER (PARTITION BY id ORDER BY event_date) AS rn
    FROM T1
)
INSERT INTO T2 (id, start_date, end_date)
SELECT 
    id,
    MAX(CASE WHEN rn % 2 = 1 THEN event_date END) AS start_date,
    MAX(CASE WHEN rn % 2 = 0 THEN event_date END) AS end_date
FROM numbered_dates
GROUP BY id, (rn - 1) / 2
ORDER BY (rn - 1) / 2;

逻辑说明

  1. 生成行号:通过ROW_NUMBER()给每个id下的记录按event_date排序生成连续行号,确保配对顺序符合日期排列;
  2. 分组配对:利用(rn - 1) / 2将行号1-2、3-4等依次归为同一组,实现两两配对;
  3. 提取起止日期:用CASE语句配合MAX()聚合函数,分别提取每组中的奇数行(起始日期)和偶数行(结束日期);
  4. 兼容奇数记录数:若某个id的记录数为奇数,最后一组的end_date会返回NULL,符合“处理完所有记录”的要求。

内容的提问来源于stack exchange,提问作者Sergey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 03:01:21