我有一个包含 4 列的表:ID、STARTDATE、ENDDATE 和 BADGE。我想根据 ID 和 BADGE 值合并行,但要确保只有连续的行才会被合并。
例如,如果输入是:
输出将是:
我尝试过滞后领先、无界、有界前导,但无法实现输出:
SELECT ID,
STARTDATE,
MAX(ENDDATE),
NAME
FROM (SELECT USERID,
IFF(LAG(NAME) over(Partition by USERID Order by STARTDATE) = NAME,
LAG(STARTDATE) over(Partition by USERID Order by STARTDATE),
STARTDATE) AS STARTDATE,
ENDDATE,
NAME
from myTable )
GROUP BY USERID,
STARTDATE,
NAME
我们必须确保仅合并具有相同 ID 和徽章的连续行。
我们将不胜感激,谢谢。
最佳答案
您可以将问题分为两个步骤:
- 创建正确的分区
- 使用直接聚合函数(
MIN
和MAX
)对分区进行聚合
当没有连续的日期匹配时,您可以使用 bool 字段 1 来完成第一步(row1.ENDDATE = row2.STARTDATE + 1 天
)。该值将指示何时应创建新分区。因此,如果您计算运行总和,您应该拥有正确编号的分区。
WITH cte AS (
SELECT *,
IFF(LAG(ENDDATE) OVER(PARTITION BY ID, Badge ORDER BY STARTDATE) + INTERVAL 1 DAY = STARTDATE , 0, 1) AS boolval
FROM tab
)
SELECT *
SUM(COALESCE(boolval, 0)) OVER(ORDER BY ID DESC, STARTDATE) AS rn
FROM cte
然后第二步可以总结为使用 MIN
和 直接聚合“STARTDATE”和“ENDDATE” MAX
函数分别根据您的排名值进行分组。为了语法正确性,您还需要在 GROUP BY
子句中添加“ID”和“Badge”,即使它们的作用范围是已被计算的排名值捕获。
WITH cte AS (
SELECT *,
IFF(LAG(ENDDATE) OVER(PARTITION BY ID, Badge ORDER BY STARTDATE) + INTERVAL 1 DAY = STARTDATE , 0, 1) AS boolval
FROM tab
), cte2 AS (
SELECT *,
SUM(COALESCE(boolval, 0)) OVER(ORDER BY ID DESC, STARTDATE) AS rn
FROM cte
)
SELECT ID,
MIN(STARTDATE) AS STARTDATE,
MAX(ENDDATE) AS ENDDATE,
Badge
FROM cte2
GROUP BY ID,
Badge,
rn
关于sql - 如何使用 Lag Lead 或窗口函数根据列值合并行开始日期结束日期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72754066/