Суммировать группу строк, начиная со значения x и продолжая до тех пор, пока не встретится значение y, а затем повторить - PullRequest
1 голос
/ 03 мая 2019

Я пытаюсь сгруппировать строки, начиная с точки, где значение больше 0, а затем до тех пор, пока значение не вернется к 0, а затем повторяюсь по таблице.

Это для MySQL 8.0... и я не уверен, с чего начать.

Пример таблицы

| tag          | value | timestamp                |
|--------------|-------|--------------------------|
| sts_downtime | 0     | 2019-01-03 09:31:40.8240 |
| sts_downtime | 1     | 2019-01-03 09:50:23.0310 |
| sts_downtime | 3     | 2019-01-03 09:53:07.7750 |
| sts_downtime | 4     | 2019-01-03 09:53:40.6060 |
| sts_downtime | 0     | 2019-01-04 08:48:27.1020 |
| sts_downtime | 0     | 2019-01-04 13:30:26.5180 |
| sts_downtime | 10    | 2019-01-04 14:19:56.3740 |
| sts_downtime | 10    | 2019-01-07 08:49:03.8480 |
| sts_downtime | 10    | 2019-01-07 09:34:25.0850 |
| sts_downtime | 0     | 2019-01-07 09:34:53.9940 |
| sts_downtime | 0     | 2019-01-07 12:59:21.3210 |

Что бы я хотел получить


| Sum of Value | Start                    | End                      |
|--------------|--------------------------|--------------------------|
| 8            | 2019-01-03 09:50:23.0310 | 2019-01-03 09:53:40.6060 |
| 30           | 2019-01-04 14:19:56.3740 | 2019-01-07 09:34:25.0850 |

Ответы [ 2 ]

1 голос
/ 03 мая 2019

С несколькими CTE:

with 
ctemin as (
  select t.timestamp from tablename t
    where value <> 0 and 
    (select value from tablename where timestamp = 
       (select max(timestamp) from tablename where timestamp < t.timestamp)
    ) = 0
),  
ctemax as (
  select t.timestamp from tablename t
    where value <> 0 and 
    (select value from tablename where timestamp = 
       (select min(timestamp) from tablename where timestamp > t.timestamp)
    ) = 0
),
cte as (
  select 
    t.timestamp Start,
    (select min(timestamp) from ctemax 
     where timestamp >= t.timestamp) End
  from ctemin t
)  

select 
  sum(value) `Sum of Value`,
  c.Start, c.End
from cte c inner join tablename t
on t.timestamp between c.Start and c.End
group by c.Start, c.End

См. Демоверсию .Результаты:

| Sum of Value | Start                      | End                        |
| ------------ | -------------------------- | -------------------------- |
| 8            | 2019-01-03 09:50:23.031000 | 2019-01-03 09:53:40.606000 |
| 30           | 2019-01-04 14:19:56.374000 | 2019-01-07 09:34:25.085000 |
0 голосов
/ 04 мая 2019

У вас есть доступ к оконным функциям в MySQL 8. Используйте их.

WITH cte1 AS (
    SELECT *, CASE
        WHEN LAG(value, 1, 0) OVER (ORDER BY timestamp) = 0 AND value > 0 THEN 1
        WHEN LAG(value, 1, 0) OVER (ORDER BY timestamp) > 0 AND value = 0 THEN 1 END AS chg
    FROM t
), cte2 AS (
    SELECT *, SUM(chg) OVER (ORDER BY timestamp) AS grp
    FROM cte1
)
SELECT SUM(value) AS `Sum of value`, MIN(timestamp) AS `Start`, MAX(timestamp) AS `End`
FROM cte2
GROUP BY grp
HAVING SUM(value) > 0

Демонстрация на дб <> скрипка

...