如何以智能方式聚合这些行?

时间:2019-05-21 17:45:37

标签: sql sql-server

我有一个表格和下面的最小样本行。我想以更聪明的方式获得预期的结果。有人有什么好主意吗?

create table foo (
    id int,
    s datetime,
    e datetime,
    value float
);

insert foo values
    (1, '2019-1-1 1:00:00', '2019-1-1 3:00:00', 10.0),
    (1, '2019-1-1 1:30:00', '2019-1-1 3:00:00', 10.0),
    (1, '2019-1-1 4:00:00', '2019-1-1 5:00:00', 10.0),
    (1, '2019-1-1 4:30:00', '2019-1-1 6:00:00', 10.0),  
    (2, '2019-1-1 2:00:00', '2019-1-1 6:00:00', 15.0),  
    (2, '2019-1-1 2:00:00', '2019-1-1 6:00:00', 10.0);

我想要这样的结果。

1, '2019-1-1 1:00:00', '2019-1-1 3:00:00', 10.0
1, '2019-1-1 4:00:00', '2019-1-1 6:00:00', 10.0 
2, '2019-1-1 2:00:00', '2019-1-1 6:00:00', 15.0

与周期重叠的行相比,它们的周期更长,s和e合并的周期将更长,并且值更大。

其他信息

我认为“智能方式”更易于理解(例如,较少的子查询可能更好),并且执行速度更快。

实际上,我在示例代码中的“ foo”表中有一个附加的地理Point列,并且必须从同一时间段组中具有最低“值”的行中选择一个Point。我曾经想过我的逻辑。没有许多子查询或游标,我不知道要获得结果。因此,我想让我的问题更简单,以便对此案有所了解。

2 个答案:

答案 0 :(得分:2)

这是一种空白和岛屿问题。您可以通过确定重叠时间段的开始时间(即某个时间段与之前的任何时间段都不重叠的时间)来解决该问题。

然后,起点的累积总和定义一个组。您可以按组进行汇总:

select id, min(s) as s, max(e) as e, max(value)
from (select f.*,
             sum(case when max_e < s then 1 else 0 end) over (partition by id order by s) as grp
      from (select f.*,
                   max(e) over (partition by id order by s rows between unbounded preceding and 1 preceding) as max_e
            from foo f
           ) f
     ) f
group by id, grp;

Here是db <>小提琴。

答案 1 :(得分:-1)

使用max()聚合函数

select id,s,e,max(value) from table
group by id,s,e