Это проблема с пробелами и островами (статья предназначена для SQL сервера, но в равной степени относится к postgresql).
Следующее должно решить вашу проблему
SELECT Location,
MAX(Value) AS Max,
SUM(CASE WHEN id = 'B' THEN Value END) AS Sum,
1.0 * SUM(CASE WHEN id = 'B' THEN Value END) / MAX(Value) AS SuccesRate
FROM ( SELECT *,
ROW_NUMBER() OVER(PARTITION BY Location, CASE WHEN Value = 0 THEN 1 ELSE 0 END ORDER BY metric_date) -
ROW_NUMBER() OVER(PARTITION BY Location ORDER BY metric_date) AS GroupingSet
FROM T
) AS t
WHERE Value <> 0
GROUP BY Location, GroupingSet;
Ключ генерирует поле для группировки, чтобы идентифицировать острова, что можно сделать, выделив два номера строки для каждой строки:
SELECT *,
ROW_NUMBER() OVER(PARTITION BY Location, CASE WHEN Value = 0 THEN 1 ELSE 0 END ORDER BY metric_date) AS RowNumInSubset,
ROW_NUMBER() OVER(PARTITION BY Location ORDER BY metric_date) AS RowNumInSet
FROM #T
ORDER BY metric_date
Это приводит к следующему:
metric_date location id value RowNumInSubset RowNumInSet
----------------------------------------------------------------------------
2020-02-07 13:00 ATL A 34 1 1
2020-02-07 13:05 ATL B 12 2 2
2020-02-07 13:10 ATL B 2 3 3
2020-02-07 13:15 ATL A 15 4 4
2020-02-07 13:20 ATL A 0 1 5
2020-02-07 13:25 ATL A 0 2 6
2020-02-07 13:30 ATL A 12 5 7
2020-02-07 13:35 ATL B 12 6 8
2020-02-07 13:40 ATL A 23 7 9
2020-02-07 13:45 ATL B 3 8 10
2020-02-07 13:50 ATL A 0 3 11
2020-02-07 13:55 ATL A 0 4 12
Затем, вычитая RowNumInSet
из RowNumInSubset
, вы получите константу для вашего islands
:
metric_date location id value RowNumInSubset RowNumInSet GroupingSet
------------------------------------------------------------------------------------
2020-02-07 13:00 ATL A 34 1 1 0
2020-02-07 13:05 ATL B 12 2 2 0
2020-02-07 13:10 ATL B 2 3 3 0
2020-02-07 13:15 ATL A 15 4 4 0
------------------------------------------------------------------------------------
2020-02-07 13:20 ATL A 0 1 5 -4
2020-02-07 13:25 ATL A 0 2 6 -4
------------------------------------------------------------------------------------
2020-02-07 13:30 ATL A 12 5 7 -2
2020-02-07 13:35 ATL B 12 6 8 -2
2020-02-07 13:40 ATL A 23 7 9 -2
2020-02-07 13:45 ATL B 3 8 10 -2
------------------------------------------------------------------------------------
2020-02-07 13:50 ATL A 0 3 11 -8
2020-02-07 13:55 ATL A 0 4 12 -8
Затем, наконец, вы можете удалить строки, где value = 0
, так как это просто точки останова:
metric_date location id value RowNumInSubset RowNumInSet GroupingSet
------------------------------------------------------------------------------------
2020-02-07 13:00 ATL A 34 1 1 0
2020-02-07 13:05 ATL B 12 2 2 0
2020-02-07 13:10 ATL B 2 3 3 0
2020-02-07 13:15 ATL A 15 4 4 0
------------------------------------------------------------------------------------
2020-02-07 13:30 ATL A 12 5 7 -2
2020-02-07 13:35 ATL B 12 6 8 -2
2020-02-07 13:40 ATL A 23 7 9 -2
2020-02-07 13:45 ATL B 3 8 10 -2
Затем вы можете выполнить агрегирование для каждой группы.
Пример для DB <> Fiddle