不同时间的汇总计算

时间:2011-01-02 20:59:11

标签: sql-server group-by totals

我有以下示例,我想在每个可用时间计算总数:

timestamp  device value
2010-12-30 00:00 1 5
2010-12-30 00:05 1 5
2010-12-30 00:05 2 10
2010-12-30 00:13 1 23
2010-12-30 00:16 3 11
2010-12-30 00:30 1 22
2010-12-30 00:40 2 55
2010-12-30 00:40 3 12
2010-12-30 00:45 2 12
2010-12-30 10:00 3 33

最后结果应如下所示:

timestamp  Total
2010-12-30 00:00 5
2010-12-30 00:05 5
2010-12-30 00:05 15
2010-12-30 00:13 33
2010-12-30 00:16 44
2010-12-30 00:30 43
2010-12-30 00:40 88
2010-12-30 00:40 89
2010-12-30 00:45 46
2010-12-30 10:00 67

我的想法是,对于每个时间戳,我需要获取每个设备的最后一个值,然后对这些值进行求和。

例如:

对于时间戳2010-12-30 00:13,我需要输入以下条目并将它们合并:

2010-12-30 00:05 2 10
2010-12-30 00:13 1 23

总数将为26.对于时间戳2010-12-30 10:00,我需要采取以下措辞:

2010-12-30 00:30 1 22
2010-12-30 00:45 2 12
2010-12-30 10:00 3 33

其中67为总数。

我的想法是创建一个查询,为每个时间戳选择每个设备的最新值,但我已经停留在为特定时间戳选择每个设备的最新值,所以我请求一些支持

1 个答案:

答案 0 :(得分:1)

这是一种方法。查询选择表中的所有行,然后使用outer apply汇总每个设备的最后一个值。 not exists查询会筛选出不是该设备最后一行的行。

select  t1.timestamp
,       last_rows_per_device.Total
from    @t t1
outer apply
        (
        select  sum(t2.value) as Total
        from    @t t2
        where   (
                    t2.timestamp < t1.timestamp
                    or (t2.timestamp = t1.timestamp and t2.device <= t1.device)
                ) 
                and not exists
                (
                    select  *
                    from    @t t3
                    where   t3.device = t2.device
                            and t2.timestamp < t3.timestamp 
                            and t3.timestamp <= t1.timestamp
                )
        ) last_rows_per_device
order by
        t1.timestamp
,       t1.device

该查询假定(timestamp, device)是唯一的,并且它按设备ID,最低设备优先顺序排列具有相同时间戳的行。

这符合您的示例输出:

timestamp             Total
2010-12-30 00:00      5
2010-12-30 00:05      5
2010-12-30 00:05      15
2010-12-30 00:13      33
2010-12-30 00:16      44
2010-12-30 00:30      43
2010-12-30 00:40      77
2010-12-30 00:40      89
2010-12-30 00:45      46
2010-12-30 10:00      67

来源数据:

declare @t table (timestamp datetime, device int, value int)
insert @t (timestamp, device, value)
          select '2010-12-30 00:00', 1, 5
union all select '2010-12-30 00:05', 1, 5
union all select '2010-12-30 00:05', 2, 10
union all select '2010-12-30 00:13', 1, 23
union all select '2010-12-30 00:16', 3, 11
union all select '2010-12-30 00:30', 1, 22
union all select '2010-12-30 00:40', 2, 55
union all select '2010-12-30 00:40', 3, 12
union all select '2010-12-30 00:45', 2, 12
union all select '2010-12-30 10:00', 3, 33