简体   繁体   中英

DB2 SQL Adding Columns Values

I am trying to add some calculated columns together where the values from those columns are substrings of a timestamp difference function between the current record and the next record. Unfortunately the substring does return null values and I have attempted to convert these via the COALESCE, ISNULL and I am not getting anywhere with this in order to get these values to add properly. I have also attempted the SUM function but i am getting error on that as well.

select T01."ENGVIDN", T01."ENGSTAT", (TIMESTAMP(((SUBSTR( T01."ENGSTME", 1, LOCATE('T', T01."ENGSTME")-1))),(SUBSTR( T01."ENGSTME", LOCATE('T', T01."ENGSTME")+1, 8)))) as "T01 TIMESTAMP",  (TIMESTAMP(((SUBSTR( T02."ENGSTME", 1, LOCATE('T', T02."ENGSTME")-1))),(SUBSTR( T02."ENGSTME", LOCATE('T', T02."ENGSTME")+1, 8)))) as "T02 TIMESTAMP",  
CAST(((TIMESTAMP(((SUBSTR( T02."ENGSTME", 1, LOCATE('T', T02."ENGSTME")-1))),(SUBSTR( T02."ENGSTME", LOCATE('T', T02."ENGSTME")+1, 8)))) - (TIMESTAMP(((SUBSTR( T01."ENGSTME", 1, LOCATE('T', T01."ENGSTME")-1))),(SUBSTR( T01."ENGSTME", LOCATE('T', T01."ENGSTME")+1, 8))))) as INT) as "DIFF",
CAST(SUBSTR(((TIMESTAMP(((SUBSTR( T02."ENGSTME", 1, LOCATE('T', T02."ENGSTME")-1))),(SUBSTR( T02."ENGSTME", LOCATE('T', T02."ENGSTME")+1, 8)))) - (TIMESTAMP(((SUBSTR( T01."ENGSTME", 1, LOCATE('T', T01."ENGSTME")-1))),(SUBSTR( T01."ENGSTME", LOCATE('T', T01."ENGSTME")+1, 8))))), LOCATE('.', ((TIMESTAMP(((SUBSTR( T02."ENGSTME", 1, LOCATE('T', T02."ENGSTME")-1))),(SUBSTR( T02."ENGSTME", LOCATE('T', T02."ENGSTME")+1, 8)))) - (TIMESTAMP(((SUBSTR( T01."ENGSTME", 1, LOCATE('T', T01."ENGSTME")-1))),(SUBSTR( T01."ENGSTME", LOCATE('T', T01."ENGSTME")+1, 8))))))-8, 2)as INT) as "DAYS",
CAST(SUBSTR(((TIMESTAMP(((SUBSTR( T02."ENGSTME", 1, LOCATE('T', T02."ENGSTME")-1))),(SUBSTR( T02."ENGSTME", LOCATE('T', T02."ENGSTME")+1, 8)))) - (TIMESTAMP(((SUBSTR( T01."ENGSTME", 1, LOCATE('T', T01."ENGSTME")-1))),(SUBSTR( T01."ENGSTME", LOCATE('T', T01."ENGSTME")+1, 8))))), LOCATE('.', ((TIMESTAMP(((SUBSTR( T02."ENGSTME", 1, LOCATE('T', T02."ENGSTME")-1))),(SUBSTR( T02."ENGSTME", LOCATE('T', T02."ENGSTME")+1, 8)))) - (TIMESTAMP(((SUBSTR( T01."ENGSTME", 1, LOCATE('T', T01."ENGSTME")-1))),(SUBSTR( T01."ENGSTME", LOCATE('T', T01."ENGSTME")+1, 8))))))-6, 2) as INT) as "HOURS",
CAST(SUBSTR(((TIMESTAMP(((SUBSTR( T02."ENGSTME", 1, LOCATE('T', T02."ENGSTME")-1))),(SUBSTR( T02."ENGSTME", LOCATE('T', T02."ENGSTME")+1, 8)))) - (TIMESTAMP(((SUBSTR( T01."ENGSTME", 1, LOCATE('T', T01."ENGSTME")-1))),(SUBSTR( T01."ENGSTME", LOCATE('T', T01."ENGSTME")+1, 8))))), LOCATE('.', ((TIMESTAMP(((SUBSTR( T02."ENGSTME", 1, LOCATE('T', T02."ENGSTME")-1))),(SUBSTR( T02."ENGSTME", LOCATE('T', T02."ENGSTME")+1, 8)))) - (TIMESTAMP(((SUBSTR( T01."ENGSTME", 1, LOCATE('T', T01."ENGSTME")-1))),(SUBSTR( T01."ENGSTME", LOCATE('T', T01."ENGSTME")+1, 8))))))-4, 2) as INT) as "MINUTES",
CAST(SUBSTR(((TIMESTAMP(((SUBSTR( T02."ENGSTME", 1, LOCATE('T', T02."ENGSTME")-1))),(SUBSTR( T02."ENGSTME", LOCATE('T', T02."ENGSTME")+1, 8)))) - (TIMESTAMP(((SUBSTR( T01."ENGSTME", 1, LOCATE('T', T01."ENGSTME")-1))),(SUBSTR( T01."ENGSTME", LOCATE('T', T01."ENGSTME")+1, 8))))), LOCATE('.', ((TIMESTAMP(((SUBSTR( T02."ENGSTME", 1, LOCATE('T', T02."ENGSTME")-1))),(SUBSTR( T02."ENGSTME", LOCATE('T', T02."ENGSTME")+1, 8)))) - (TIMESTAMP(((SUBSTR( T01."ENGSTME", 1, LOCATE('T', T01."ENGSTME")-1))),(SUBSTR( T01."ENGSTME", LOCATE('T', T01."ENGSTME")+1, 8))))))-2, 2) as INT) as "SECONDS",
--
(CAST(SUBSTR(((TIMESTAMP(((SUBSTR( T02."ENGSTME", 1, LOCATE('T', T02."ENGSTME")-1))),(SUBSTR( T02."ENGSTME", LOCATE('T', T02."ENGSTME")+1, 8)))) - (TIMESTAMP(((SUBSTR( T01."ENGSTME", 1, LOCATE('T', T01."ENGSTME")-1))),(SUBSTR( T01."ENGSTME", LOCATE('T', T01."ENGSTME")+1, 8))))), LOCATE('.', ((TIMESTAMP(((SUBSTR( T02."ENGSTME", 1, LOCATE('T', T02."ENGSTME")-1))),(SUBSTR( T02."ENGSTME", LOCATE('T', T02."ENGSTME")+1, 8)))) - (TIMESTAMP(((SUBSTR( T01."ENGSTME", 1, LOCATE('T', T01."ENGSTME")-1))),(SUBSTR( T01."ENGSTME", LOCATE('T', T01."ENGSTME")+1, 8))))))-4, 2) as INT)*60 +
CAST(SUBSTR(((TIMESTAMP(((SUBSTR( T02."ENGSTME", 1, LOCATE('T', T02."ENGSTME")-1))),(SUBSTR( T02."ENGSTME", LOCATE('T', T02."ENGSTME")+1, 8)))) - (TIMESTAMP(((SUBSTR( T01."ENGSTME", 1, LOCATE('T', T01."ENGSTME")-1))),(SUBSTR( T01."ENGSTME", LOCATE('T', T01."ENGSTME")+1, 8))))), LOCATE('.', ((TIMESTAMP(((SUBSTR( T02."ENGSTME", 1, LOCATE('T', T02."ENGSTME")-1))),(SUBSTR( T02."ENGSTME", LOCATE('T', T02."ENGSTME")+1, 8)))) - (TIMESTAMP(((SUBSTR( T01."ENGSTME", 1, LOCATE('T', T01."ENGSTME")-1))),(SUBSTR( T01."ENGSTME", LOCATE('T', T01."ENGSTME")+1, 8))))))-2, 2) as INT))



from mrc_main."SAMENGST" T01 
        INNER JOIN mrc_main."SAMENGST" T02 on RRN(T02) = RRN(T01)+1
                and (TIMESTAMP(((SUBSTR( T02."ENGSTME", 1, LOCATE('T', T02."ENGSTME")-1))),(SUBSTR( T02."ENGSTME", LOCATE('T', T02."ENGSTME")+1, 8)))) > (TIMESTAMP(((SUBSTR( T01."ENGSTME", 1, LOCATE('T', T01."ENGSTME")-1))),(SUBSTR( T01."ENGSTME", LOCATE('T', T01."ENGSTME")+1, 8))))


WHERE T01."ENGVIDN" = T02."ENGVIDN" and
        T02."ENGVIDN" = 212014918948687 and 
        T01."ENGSTME" like '%2020-02-17%' 

I am trying to add the columns labeled as DAYS, HOURS, MINUTES, SECONDS so what would be the correct way to accomplish this?

Sample Data Below

ENGVIDN         ENGSTME                 ENGSTME
212014918948687 2020-02-17T09:46:19Z    Off
212014918948687 2020-02-17T09:46:29Z    On
212014918948687 2020-02-17T09:50:10Z    Idle
212014918948687 2020-02-17T10:01:11Z    On
212014918948687 2020-02-17T10:12:16Z    Idle
212014918948687 2020-02-17T11:10:17Z    On
212014918948687 2020-02-17T11:19:27Z    Idle
212014918948687 2020-02-17T11:23:27Z    On
212014918948687 2020-02-17T11:35:19Z    Idle
212014918948687 2020-02-17T11:36:53Z    Off
212014918948687 2020-02-17T12:07:20Z    On
212014918948687 2020-02-17T12:09:20Z    Idle
212014918948687 2020-02-17T12:21:01Z    On
212014918948687 2020-02-17T12:38:48Z    Idle
212014918948687 2020-02-17T12:39:47Z    On
212014918948687 2020-02-17T12:53:44Z    Idle
212014918948687 2020-02-17T12:56:23Z    On
212014918948687 2020-02-17T12:58:48Z    Idle
212014918948687 2020-02-17T13:01:14Z    On
212014918948687 2020-02-17T13:17:17Z    Idle
212014918948687 2020-02-17T14:01:01Z    On
212014918948687 2020-02-17T14:09:16Z    Idle
212014918948687 2020-02-17T14:41:29Z    On
212014918948687 2020-02-17T15:01:19Z    Off
212014918948687 2020-02-17T15:35:42Z    On
212014918948687 2020-02-17T15:43:11Z    Off
212014918948687 2020-02-17T16:16:57Z    On
212014918948687 2020-02-17T16:26:36Z    Idle
212014918948687 2020-02-17T16:50:30Z    On
212014918948687 2020-02-17T16:58:20Z    Idle
212014918948687 2020-02-17T17:03:24Z    On
212014918948687 2020-02-17T17:13:30Z    Idle
212014918948687 2020-02-17T17:23:16Z    On
212014918948687 2020-02-17T17:36:51Z    Off
212014918948687 2020-02-17T19:00:35Z    On
212014918948687 2020-02-17T19:19:31Z    Off
212014918948687 2020-02-17T19:21:58Z    On
212014918948687 2020-02-17T19:24:09Z    Idle
212014918948687 2020-02-17T19:26:08Z    On
212014918948687 2020-02-17T19:42:24Z    Idle
212014918948687 2020-02-17T19:44:27Z    On
212014918948687 2020-02-17T19:48:55Z    Off
212014918948687 2020-02-17T19:50:53Z    On
212014918948687 2020-02-17T19:57:27Z    Off
212014918948687 2020-02-18T01:55:56Z    On
212014918948687 2020-02-18T01:58:43Z    Off
212014918948687 2020-02-18T05:02:17Z    Off
212014918948687 2020-02-18T08:58:01Z    On
212014918948687 2020-02-18T09:01:45Z    Idle
212014918948687 2020-02-18T09:05:17Z    On

I'm not sure but it seems that it's V7.1.
Try this as is:

WITH TAB (ENGSTME) AS 
(
VALUES
  TIMESTAMP('2020-02-17-09.46.19')
, TIMESTAMP('2020-02-17-09.46.29')
, TIMESTAMP('2020-02-17-09.50.10')
, TIMESTAMP('2020-02-17-10.01.11')
, TIMESTAMP('2020-02-17-10.12.16')
, TIMESTAMP('2020-02-17-11.10.17')
)
, TAB_ENUM (RN, ENGSTME) AS 
(
SELECT ROWNUMBER() OVER (ORDER BY ENGSTME) AS RN, ENGSTME
FROM TAB
)
SELECT 
  A.ENGSTME, B.ENGSTME AS ENGSTME_PREV
, DIGITS(DEC(A.ENGSTME - B.ENGSTME, 14)) AS TS_DURATION --yyyymmddhhmmss format with leading zeroes
, (DAYS(A.ENGSTME) - DAYS(B.ENGSTME)) * 86400 + MIDNIGHT_SECONDS(A.ENGSTME) - MIDNIGHT_SECONDS(B.ENGSTME) AS TS_DIFF_SEC
FROM TAB_ENUM A
LEFT JOIN TAB_ENUM B ON B.RN = A.RN - 1 
ORDER BY A.ENGSTME;

The result is:

|ENGSTME            |ENGSTME_PREV       |TS_DURATION   |TS_DIFF_SEC|
|-------------------|-------------------|--------------|-----------|
|2020-02-17 09:46:19|                   |              |           |
|2020-02-17 09:46:29|2020-02-17 09:46:19|00000000000010|10         |
|2020-02-17 09:50:10|2020-02-17 09:46:29|00000000000341|221        |
|2020-02-17 10:01:11|2020-02-17 09:50:10|00000000001101|661        |
|2020-02-17 10:12:16|2020-02-17 10:01:11|00000000001105|665        |
|2020-02-17 11:10:17|2020-02-17 10:12:16|00000000005801|3481       |

The idea is to enumerate the rows first, and then rejoin rows to get previous timestamp in an additional column for a current row. You may do such an enumeration for each group (if any), and not for the entire data set as in the example (add the corresponding PARTITION BY clause inside OVER at the beginning and the columns of such a group in JOIN ).
You may use TS_DURATION column or use your own calculation on TS_DIFF_SEC to get additional columns you want.

Please, provide the exact result desired on this sample data, If this is not you want.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM