【问题标题】:SQL Query - Combine rows based on multiple columnsSQL 查询 - 基于多列组合行
【发布时间】:2023-11-22 08:28:01
【问题描述】:

在上图中,我想在连续几天合并具有相同值的行。 合并的行将在 From 列上具有最早日期,在 To 列上具有最晚日期。 看示例,即使第 3 行和第 4 行具有相同的值,它们也不会因为日期间隔而合并。

我尝试过使用 LAG 和 LEAD 函数,但没有成功。

【问题讨论】:

  • 标记您的数据库名称
  • 什么意思?
  • 是 mysql,sqlserver,postgrey 还是 oralce 还是其他的
  • 好的。知道了。谢谢!

标签: sql sql-server merge rows


【解决方案1】:

我将推荐以下方法:

  1. 查找每个新组的开始位置。为此,您可以将之前的最大值 todate 与此行中的 fromdate 进行比较。
  2. 对开始次数进行累积求和以定义一个组。
  3. 汇总结果。

这可以使用窗口函数和聚合来处理:

select value, min(fromdate) as fromdate, max(todate) as todate
from (select t.*,
             sum(case when prev_todate >= dateadd(day, -1, fromdate)
                      then 0   -- overlap, so this does not begin a new group
                      else 1   -- no overlap, so this does begin a new group
                 end) over
                 (partition by value order by fromdate) as grp
      from (select t.*,
                   max(todate) over (partition by value
                                     order by fromdate
                                     rows between unbounded preceding and 1 preceding
                                    ) as prev_todate
            from t
           ) t
     ) t
 group by value, grp
 order by value, min(fromdate);

Here 是一个 dbfiddle。

【讨论】:

    【解决方案2】:

    你可以试试下面的方法-

    DEMO

        with c as
        (
        select *, datediff(dd,todate,laedval) as leaddiff,
        datediff(dd,todate,lagval) as lagdiff
        from
        (
        select *,lead(todate) over(partition by value order by todate) laedval,
        lag(todate) over(partition by value order by todate) lagval
        from t1
        )A
        ) 
    
    
    
    select * from
    (
    select value,min(todate) as fromdate,max(todate) as todate from c
        where coalesce(leaddiff,0)+coalesce(lagdiff,0) in (1,-1)
        group by value
        union all
        select value,fromdate,todate from c
        where coalesce(leaddiff,0)+coalesce(lagdiff,0)>1 or coalesce(leaddiff,0)+coalesce(lagdiff,0)<-1
    )A order by value
    

    输出:

    value   fromdate            todate
    1       16/07/2019 00:00:00 17/07/2019 00:00:00
    3       21/07/2019 00:00:00 26/07/2019 00:00:00
    2       18/07/2019 00:00:00 18/07/2019 00:00:00
    2       20/07/2019 00:00:00 20/07/2019 00:00:00
    

    【讨论】:

    • 抱歉,经过一些测试,我在将第 9 行和第 10 行的值更改为“1”时遇到了问题。它没有返回预期的输出。