Сводный расчет за разное время - PullRequest
1 голос
/ 02 января 2011

У меня есть следующий пример, для которого я хотел бы рассчитать итоги в каждый доступный момент времени:

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 Ответ

1 голос
/ 03 января 2011

Вот один из подходов. Запрос выбирает все строки из таблицы, а затем использует 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) уникален, и он упорядочивает строки с одинаковой отметкой времени по идентификатору устройства, сначала наименьшее устройство.

Это соответствует вашему примеру вывода:

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
...