Вычислить продолжительность на основе даты и времени следующей строки и почасовых данных GroupBy в PostgreSQL - PullRequest
0 голосов
/ 26 мая 2020

Мне нужно найти продолжительность для каждого процесса в PostgreSQL.


DROP TABLE IF EXISTS "Process";
CREATE TABLE "Process" (
    "StartTime" TIMESTAMP,
    "State" VARCHAR (255) NOT NULL,
    "Remark" VARCHAR (255) NOT NULL
);

INSERT INTO public."Process"(
    "StartTime", "State","Remark")
    VALUES 
    ('2020-5-13 07:30:00','RUN',FALSE),
    ('2020-5-13 08:25:00','ASSIST', FALSE),
    ('2020-5-13 08:30:00','STOP', FALSE),
    ('2020-5-13 08:40:00','RUN', FALSE),
    ('2020-5-13 09:40:00','RUN', FALSE);



Продолжительность рассчитывается на основе следующей строки «StartTime» минус текущая строка «StartTime». Эту часть легко найти на интернет-ресурсе. Но мне нужно найти продолжительность на основе данных о почасовом отключении. Пример: каждый час имеет свой собственный процесс и продолжительность.

Ожидаемый результат:

StartTime                NextRowStartTime     Hour                  State             Duration
'2020-5-13 07:30:00'  '2020-5-13 08:00:00'   '2020-5-13 07:00:00'   'RUN'             30
'2020-5-13 08:00:00'  '2020-5-13 08:25:00'   '2020-5-13 08:00:00'   'RUN'             25
'2020-5-13 08:25:00'  '2020-5-13 08:30:00'   '2020-5-13 08:00:00'   'ASSIST'          5
'2020-5-13 08:30:00'  '2020-5-13 08:40:00'   '2020-5-13 08:00:00'   'STOP'            10
'2020-5-13 08:40:00'  '2020-5-13 09:00:00'   '2020-5-13 08:00:00'   'RUN'             20
'2020-5-13 09:00:00'  '2020-5-13 09:40:00'   '2020-5-13 09:00:00'   'RUN'             40

Как вы можете видеть из выходных данных на '2020-5-13 07:30:00', это станет 2 результатом до 8 утра и после 8 утра. Есть идеи решить это? (можно игнорировать столбец примечаний)

1 Ответ

0 голосов
/ 26 мая 2020

Сначала создайте другую таблицу для 24-часового целого числа

CREATE TABLE "HourGroup" (
    "H" INT UNIQUE NOT NULL
);   

INSERT INTO public."HourGroup"("H")
VALUES
('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'),('10'),('11'),('12'),('13'),('14'),('15'),('16'),('17'),('18'),('19'),('20'),('21'),('22'),('23');  

Затем используйте LEAD () для получения данных следующей строки

select
    "State",
    "Remark",
    "StartTime",
    LEAD("StartTime",1) over ( order by "StartTime") "EndAt"
from "Process"

Следующее соединение с другой таблицей

select A."State"
      ,"Remark"
      ,"StartTime"
      ,case when DATE_PART('hour',A."StartTime") = B."H" Then A."StartTime" ELSE ( DATE_TRUNC('day',A."StartTime")::timestamp + interval '1 hour'*(B."H")) END as  "HourStartTime"
      ,case when DATE_PART('hour',A."StartTime") = B."H" Then (case when B."H" = DATE_PART('hour',A."EndAt") Then "EndAt" ELSE  ( DATE_TRUNC('day',A."EndAt")::timestamp + interval '1 hour'*(B."H"+1)) END) ELSE (case when B."H" < DATE_PART('hour',A."EndAt") Then ( DATE_TRUNC('day',A."EndAt")::timestamp + interval '1 hour'*(B."H"+1)) ELSE "EndAt" END) END as  "HourEndTime"
 From "previousresult" A
 Join "HourGroup" B on "H" between DATE_PART('hour',"StartTime") and DATE_PART('hour',"EndAt")

Окончательный запрос для расчета продолжительности.

select
    "State",
    "ProcessID",
    "Remark",
    "StartTime",
    "HourStartTime",
    "HourEndTime",
    SUM(("HourEndTime" - "HourStartTime")) as "Duration"
from cte2
group by "State","ProcessID","Remark","StartTime","HourStartTime","HourEndTime"
order by "StartTime"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...