Home > Software engineering >  Calculate the number of days spent at each station for each item in oracle plsql
Calculate the number of days spent at each station for each item in oracle plsql

Time:11-28

Having the log table as below:

| prod_id  | station_id |             date_in          |
| -------- | ---------- | ---------------------------- |
| p1       |    s1      |  2022-09-01 12:06:41.6216195 |
| p2       |    s1      |  2022-09-02 10:06:14.6216195 |
| p2       |    s2      |  2022-09-02 02:04:55.6216195 |
| p1       |    s2      |  2022-09-02 11:06:40.6216195 |
| p3       |    s1      |  2022-09-02 04:06:23.6216195 |
| p1       |    s3      |  2022-09-03 12:00:33.6216195 |
| p2       |    s1      |  2022-09-04 02:06:44.6216195 |
| p1       |    s4      |  2022-09-04 07:12:20.6216195 |
| p2       |    s2      |  2022-09-05 03:04:21.6216195 |
| p2       |    s3      |  2022-09-07 05:17:35.6216195 |
| p1       |    s3      |  2022-09-08 14:50:54.6216195 |
| p1       |    s4      |  2022-09-10 09:08:10.6216195 |
| p1       |    s5      |  2022-09-11 11:22:47.6216195 |

How can I calculate the total time (in day) spent in each station for each product?

For example to calculate the number of days spent for p1:

| prod_id  | station_id |    date_in   |       sysdate = (2022-09-13)       |
| -------- | ---------- | ------------ | ---------------------------------- |
| p1       |    s1      |  2022-09-01  |  (2022-09-02) - (2022-09-01) = 1   |
| p1       |    s2      |  2022-09-02  |  (2022-09-03) - (2022-09-02) = 1   |  
| p1       |    s3      |  2022-09-03  |  (2022-09-04) - (2022-09-03) = 1   |
| p1       |    s4      |  2022-09-04  |  (2022-09-08) - (2022-09-04) = 2   |
| p1       |    s3      |  2022-09-08  |  (2022-09-10) - (2022-09-08) = 2   |
| p1       |    s4      |  2022-09-10  |  (2022-09-11) - (2022-09-10) = 2   |
| p1       |    s5      |  2022-09-11  |     sysdate   - (2022-09-11) = 2   |

result for p1:

 | prod_id  | s1 | s2 | s3  |  s4 | s5 | s6 |...
 | -------- | -- | -- | --  |  -- | -- | -- |...
 |    p1    |  1 |  1 | 1 2 | 2 2 |  2 |  0 |...   

Finally the result should look like this:

 | prod_id  | s1 | s2 | s3 | s4 | s5 | s6 |...
 | -------- | -- | -- | -- | -- | -- | -- |...
 |    p1    |  1 |  1 |  3 |  4 |  2 |  0 |...
 |    p2    |  1 |  4 |  0 |  0 |  0 |  0 |...
 |    p3    | 11 |  0 |  0 |  0 |  0 |  0 |...

For the last record of each product, sysdate should be considered for calculation.

The Staions are not in any particular order (The log table can only be sorted by date_in).

i'm using oracle 11g.

CodePudding user response:

You can use the LEAD analytic function to find the difference from the next date and then find the number of days and PIVOT:

SELECT prod_id,
       COALESCE(s1, 0) AS s1,
       COALESCE(s2, 0) AS s2,
       COALESCE(s3, 0) AS s3,
       COALESCE(s4, 0) AS s4,
       COALESCE(s5, 0) AS s5,
       COALESCE(s6, 0) AS s6
FROM   (
  SELECT prod_id,
         station_id,
         ROUND(
           EXTRACT(DAY FROM diff)
             EXTRACT(HOUR FROM diff)/24
             EXTRACT(MINUTE FROM diff)/24/60
             EXTRACT(SECOND FROM diff)/24/60/60,
           5
         ) AS days_diff
  FROM   (
    SELECT prod_id,
           station_id,
           LEAD(date_in, 1, SYSDATE) OVER (
             PARTITION BY prod_id
             ORDER BY date_in
           ) - date_in AS diff
    FROM   table_name
  )
)
PIVOT (
  SUM(days_diff)
  FOR station_id IN (
    's1' AS s1,
    's2' AS s2,
    's3' AS s3,
    's4' AS s4,
    's5' AS s5,
    's6' AS s6
  )
)

Which, for your sample data:

CREATE TABLE table_name ( prod_id, station_id, date_in ) AS
SELECT 'p1', 's1', TIMESTAMP '2022-09-01 12:06:41.6216195' FROM DUAL UNION ALL
SELECT 'p2', 's1', TIMESTAMP '2022-09-02 10:06:14.6216195' FROM DUAL UNION ALL
SELECT 'p2', 's2', TIMESTAMP '2022-09-02 02:04:55.6216195' FROM DUAL UNION ALL
SELECT 'p1', 's2', TIMESTAMP '2022-09-02 11:06:40.6216195' FROM DUAL UNION ALL
SELECT 'p3', 's1', TIMESTAMP '2022-09-02 04:06:23.6216195' FROM DUAL UNION ALL
SELECT 'p1', 's3', TIMESTAMP '2022-09-03 12:00:33.6216195' FROM DUAL UNION ALL
SELECT 'p2', 's1', TIMESTAMP '2022-09-04 02:06:44.6216195' FROM DUAL UNION ALL
SELECT 'p1', 's4', TIMESTAMP '2022-09-04 07:12:20.6216195' FROM DUAL UNION ALL
SELECT 'p2', 's2', TIMESTAMP '2022-09-05 03:04:21.6216195' FROM DUAL UNION ALL
SELECT 'p2', 's3', TIMESTAMP '2022-09-07 05:17:35.6216195' FROM DUAL UNION ALL
SELECT 'p1', 's3', TIMESTAMP '2022-09-08 14:50:54.6216195' FROM DUAL UNION ALL
SELECT 'p1', 's4', TIMESTAMP '2022-09-10 09:08:10.6216195' FROM DUAL UNION ALL
SELECT 'p1', 's5', TIMESTAMP '2022-09-11 11:22:47.6216195' FROM DUAL

Outputs:

PROD_ID S1 S2 S3 S4 S5 S6
p1 .95832 1.03742 2.56184 5.41193 78.06039 0
p2 2.70702 2.42677 82.314 0 0 0
p3 87.36344 0 0 0 0 0

fiddle

  • Related