【问题标题】:Aggregates with DB2 results based on multiple conditions基于多个条件与 DB2 结果聚合
【发布时间】:2019-10-04 14:18:29
【问题描述】:

我正在尝试找出基于多个因素聚合 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(从每个活动到暂停的时间或活动到完成,因为一个任务可能是活动的然后暂停,然后再次活动,然后完成)

我希望得到与此类似的结果,但我只是不太知道如何正确汇总:

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 获得这些总和列和聚合时间

【问题讨论】:

    标签: sql db2 db2-400


    【解决方案1】:

    用于 LUW 的 Db2

    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;
    

    用于 iSeries 和 LUW 的 DB2

    似乎 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            |
    

    【讨论】:

    • 请原谅这个可能很愚蠢的问题:如果我在没有示例数据的情况下直接在我的数据库中运行它,那么我可以从第一个选择正确开始?
    • 插入您的 SELECT 语句(仅返回 VEHICLE_ID、JOB_STATUS、JOB_STATUS_TIME 列)而不是 VALUES (...), ..., (...) 块。
    • 明白了,谢谢。由于我和您的示例的某种原因,它们都给了我一个令牌错误Token ( was not valid. Valid tokens: , FROM INTO
    • 我不肯定,但我认为它发生在第一个...JOB_STATUS_TIME) AS (
    • 实际上它似乎可能是第二个选项, A AS (SELECT...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 2022-01-07
    • 2020-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多