Агрегируется с результатами DB2 на основе нескольких условий - PullRequest
0 голосов
/ 04 октября 2019

Я пытаюсь найти наилучший способ агрегирования результатов и группировок DB2 на основе нескольких факторов.

В настоящее время у меня есть этот запрос:

SELECT
    T1.VEHICLE,
    T2.VEHICLE_ID,
    T3.WORK_ORDER_ID,
    T3.JOB_CREATION,
    T5.JOB_STATUS,
    T4.JOB_STATUS_TIME
FROM SCHEMA.VEHICLE T1
INNER JOIN SCHEMA.VEHICLE_TO_WORK_ORDER T2
ON T1.VEHICLE_ID = T2.VEHICLE_ID
INNER JOIN SCHEMA.WORK_ORDER T3
ON T2.WORK_ORDER_ID = T3.WORK_ORDER_ID
INNER JOIN SCHEMA.WORK_ORDER_TO_JOB_STATUS T4
ON T3.WORK_ORDER_ID = T4.WORK_ORDER_ID
INNER JOIN SCHEMA.JOB_STATUS T5
ON T4.JOB_STATUS_ID = T5.JOB_STATUS_ID;

Возвращает эти результаты,которые верны с точки зрения данных:

VEHICLE    VEHICLE_ID   WORK_ORDER_ID           JOB_CREATION           JOB_STATUS          JOB_STATUS_TIME          
------------------------------------------------------------------------------------------------------------------
VEHICLE 6     6             12345       2019-09-25 00:00:09.426178      CREATED         2019-09-25 00:00:09.469059
VEHICLE 6     6             12345       2019-09-25 00:00:09.426178      ACTIVE          2019-09-25 13:40:00.981891
VEHICLE 6     6             12345       2019-09-25 00:00:09.426178      COMPLETED       2019-09-25 13:45:02.748800
VEHICLE 7     7             54321       2019-09-26 00:00:09.426178      CREATED         2019-09-26 00:00:09.469059
VEHICLE 7     7             54321       2019-09-26 00:00:09.426178      ACTIVE          2019-09-26 13:40:00.981891
VEHICLE 7     7             54321       2019-09-26 00:00:09.426178      PAUSED          2019-09-26 14:40:02.748800
VEHICLE 7     7             54321       2019-09-26 00:00:09.426178      ACTIVE          2019-09-26 14:45:09.469059
VEHICLE 7     7             54321       2019-09-26 00:00:09.426178      COMPLETED       2019-09-26 14:50:00.981891
VEHICLE 3     3             12346       2019-09-27 00:00:09.426178      OPEN            2019-09-27 13:40:02.748800
VEHICLE 3     3             12346       2019-09-27 00:00:09.426178      ACTIVE          2019-09-27 13:45:09.469059
VEHICLE 3     3             12346       2019-09-27 00:00:09.426178      PAUSED          2019-09-27 13:50:00.981891
VEHICLE 3     3             12346       2019-09-27 00:00:09.426178      CANCELLED       2019-09-27 13:51:02.748800

Здесь я пытаюсь группировать по транспортному средству и получать рабочие задания для этого транспортного средства в заданном диапазоне дат, а затем суммировать время или время активностимежду действиями, чтобы я мог получить агрегацию для столбцов суммы (в этом примере 3 транспортных средства только с одним рабочим заданием каждое, но я хочу иметь возможность просматривать любые рабочие задания в диапазоне дат и получать те же агрегаты.)

Я хочу получить счетчик каждого созданного рабочего задания, а также каждого заказа, который закончился завершенным или отмененным для их собственного столбца, но я хочу общее активное время, которое составляет job_status_time (время от каждого активного до приостановленногоили активен для завершения, поскольку задача может быть активной, затем приостановлена, затем снова активна, а затем завершена)

Я надеюсь на разрешениеults похож на это, но я просто не знаю, как правильно сгруппировать это:

VEHICLE    Created    Completed    Cancelled    Total Active Time (minutes)
------------------------------------------------------------------
6           1           1           0               5
7           1           1           0               65
3           1           0           1               5

Как я могу сгруппировать эти результаты по транспортным средствам и при этом получить эти столбцы суммы и суммарное время на основе job_status

1 Ответ

1 голос
/ 04 октября 2019

Db2 для LUW

WITH 
  RES (VEHICLE_ID, JOB_STATUS, JOB_STATUS_TIME) AS 
(
VALUES
  (6, 'CREATED',   TIMESTAMP('2019-09-25-00.00.09.469059'))
, (6, 'ACTIVE',    TIMESTAMP('2019-09-25-13.40.00.981891'))
, (6, 'COMPLETED', TIMESTAMP('2019-09-25-13.45.02.748800'))

, (7, 'CREATED',   TIMESTAMP('2019-09-26-00.00.09.469059'))
, (7, 'ACTIVE',    TIMESTAMP('2019-09-26-13.40.00.981891'))
, (7, 'PAUSED',    TIMESTAMP('2019-09-26-14.40.02.748800'))
, (7, 'ACTIVE',    TIMESTAMP('2019-09-26-14.45.09.469059'))
, (7, 'COMPLETED', TIMESTAMP('2019-09-26-14.50.00.981891'))

, (3, 'OPEN',      TIMESTAMP('2019-09-27-13.40.02.748800'))
, (3, 'ACTIVE',    TIMESTAMP('2019-09-27-13.45.09.469059'))
, (3, 'PAUSED',    TIMESTAMP('2019-09-27-13.50.00.981891'))
, (3, 'CANCELLED', TIMESTAMP('2019-09-27-13.51.02.748800'))
)
, A AS 
(
SELECT 
  VEHICLE_ID, JOB_STATUS
, JOB_STATUS_TIME
, LEAD (JOB_STATUS_TIME) OVER (PARTITION BY VEHICLE_ID ORDER BY JOB_STATUS_TIME) AS JOB_STATUS_TIME_NEXT
FROM RES
)
SELECT
  VEHICLE_ID
, COUNT(CASE JOB_STATUS WHEN 'CREATED'   THEN 1 END) AS CREATED
, COUNT(CASE JOB_STATUS WHEN 'COMPLETED' THEN 1 END) AS COMPLETED
, COUNT(CASE JOB_STATUS WHEN 'CANCELLED' THEN 1 END) AS CANCELLED
, SUM 
  (
  CASE JOB_STATUS WHEN 'ACTIVE' THEN 
    (DAYS(JOB_STATUS_TIME_NEXT) - DAYS(JOB_STATUS_TIME)) * 86400 
  + MIDNIGHT_SECONDS(JOB_STATUS_TIME_NEXT) - MIDNIGHT_SECONDS(JOB_STATUS_TIME) 
  END
  ) / 60 AS ACTIVE_MINUTES
FROM A
GROUP BY VEHICLE_ID;

DB2 для iSeries & LUW

Кажется, что в DB2 for iSeries (по крайней мере, мой 7.3) есть ошибка - попытка использовать выражение DAYS(JOB_STATUS_TIME_NEXT)в приведенном выше запросе результат SQLCODE = -171. Я понятия не имею, в чем причина: если это из-за аргумента функции, полученного из функции OLAP, или по какой-то другой причине ...

Но мы можем переписать запрос следующим образом:

WITH 
  RES (VEHICLE_ID, JOB_STATUS, JOB_STATUS_TIME) AS 
(
VALUES
  (6, 'CREATED',   TIMESTAMP('2019-09-25-00.00.09.469059'))
, (6, 'ACTIVE',    TIMESTAMP('2019-09-25-13.40.00.981891'))
, (6, 'COMPLETED', TIMESTAMP('2019-09-25-13.45.02.748800'))

, (7, 'CREATED',   TIMESTAMP('2019-09-26-00.00.09.469059'))
, (7, 'ACTIVE',    TIMESTAMP('2019-09-26-13.40.00.981891'))
, (7, 'PAUSED',    TIMESTAMP('2019-09-26-14.40.02.748800'))
, (7, 'ACTIVE',    TIMESTAMP('2019-09-26-14.45.09.469059'))
, (7, 'COMPLETED', TIMESTAMP('2019-09-26-14.50.00.981891'))

, (3, 'OPEN',      TIMESTAMP('2019-09-27-13.40.02.748800'))
, (3, 'ACTIVE',    TIMESTAMP('2019-09-27-13.45.09.469059'))
, (3, 'PAUSED',    TIMESTAMP('2019-09-27-13.50.00.981891'))
, (3, 'CANCELLED', TIMESTAMP('2019-09-27-13.51.02.748800'))
)
, A AS 
(
SELECT 
  VEHICLE_ID, JOB_STATUS
, JOB_STATUS_TIME
, ROWNUMBER() OVER (PARTITION BY VEHICLE_ID ORDER BY JOB_STATUS_TIME) AS RN
FROM RES
)
SELECT
  A1.VEHICLE_ID
, COUNT(CASE A1.JOB_STATUS WHEN 'CREATED'   THEN 1 END) AS CREATED
, COUNT(CASE A1.JOB_STATUS WHEN 'COMPLETED' THEN 1 END) AS COMPLETED
, COUNT(CASE A1.JOB_STATUS WHEN 'CANCELLED' THEN 1 END) AS CANCELLED
, SUM 
  (
  CASE A1.JOB_STATUS WHEN 'ACTIVE' THEN 
    (DAYS(A2.JOB_STATUS_TIME) - DAYS(A1.JOB_STATUS_TIME)) * 86400 
  + MIDNIGHT_SECONDS(A2.JOB_STATUS_TIME) - MIDNIGHT_SECONDS(A1.JOB_STATUS_TIME) 
  END
  ) / 60 AS ACTIVE_MINUTES
FROM A A1
LEFT JOIN A A2 ON A2.VEHICLE_ID = A1.VEHICLE_ID AND A2.RN = A1.RN + 1
GROUP BY A1.VEHICLE_ID;

Результат:

|VEHICLE_ID |CREATED    |COMPLETED  |CANCELLED  |ACTIVE_MINUTES|
|-----------|-----------|-----------|-----------|--------------|
|3          |0          |0          |1          |4             |
|6          |1          |1          |0          |5             |
|7          |1          |1          |0          |64            |
...