如何编写能够修改查询结果的SELECT语句
解决连续类别组统一起始日期的SQL查询方案
要实现你需要的效果——将连续相同类别的记录组内所有记录的Startdate替换为该组第一条记录的Startdate,核心是先识别出连续的类别分组,再在每个分组内提取首条记录的起始日期。下面是具体的实现方案:
思路解析
- 划分连续类别组:通过窗口函数对比当前行与上一行的
Category,当类别发生变化时标记为新组,再累加标记值生成唯一的组ID,把连续相同类别的记录归为同一组。 - 替换起始日期:在每个组内,使用窗口函数提取该组第一条记录的
Startdate,替换掉当前行的原始Startdate。
完整SQL代码
假设你的表名为your_table,执行以下查询即可得到期望结果:
SELECT ID, FIRST_VALUE(Startdate) OVER (PARTITION BY group_id ORDER BY ID) AS Startdate, Enddate, Category FROM ( SELECT *, -- 生成连续组的ID:当当前类别与上一行不同时,累加1 SUM(CASE WHEN Category = LAG(Category) OVER (ORDER BY ID) THEN 0 ELSE 1 END) OVER (ORDER BY ID) AS group_id FROM your_table ) AS grouped_data ORDER BY ID;
代码说明
- 子查询部分:
LAG(Category) OVER (ORDER BY ID):获取当前行的上一行Category值(ID为0的记录没有上一行,返回NULL)。CASE语句:如果当前行与上一行类别相同,返回0;否则返回1。SUM(...) OVER (ORDER BY ID):累加上述CASE的结果,生成连续组的唯一ID(比如ID0-3的组ID为1,ID4-5为2,ID6为3)。
- 外层查询部分:
FIRST_VALUE(Startdate) OVER (PARTITION BY group_id ORDER BY ID):在每个组内,按ID排序取第一条记录的Startdate,作为该组所有记录的Startdate值。
验证结果
执行后会得到你期望的输出:
| ID | Startdate | Enddate | Category |
|---|---|---|---|
| 0 | "2021-05-05" | "2021-05-20" | "First Category" |
| 1 | "2021-05-05" | "2021-05-10" | "First Category" |
| 2 | "2021-05-05" | "2021-05-10" | "First Category" |
| 3 | "2021-05-05" | "2021-05-15" | "First Category" |
| 4 | "2021-05-20" | "2021-05-22" | "Second Category" |
| 5 | "2021-05-20" | "2021-05-24" | "Second Category" |
| 6 | "2021-05-23" | "2021-05-24" | "First Category" |
注意:这个方案适用于支持窗口函数的数据库(如MySQL 8.0+、PostgreSQL、SQL Server、Oracle等),如果是老版本数据库,可能需要使用变量来实现分组逻辑。
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

