2

This is written in Oracle 11g or 12c...

Hello,

I am attempting to shape this data into hours of downtime for the previous 12 months, shaped this way to support a graph.

In the Oracle SQL query below, the commented query "M" shows how to put in one record per month. The query "M" shows the final shape I need, except that I need the downtime minutes to fall into each monthly bin.

The data however, is provided by query "D", which I have mocked up for the sake of this example. Of course, a better example might show more edge cases, such as spanning the first of a month, etc. But this example will suffice.

WITH 
/*
  M AS (  
    SELECT ADD_MONTHS (TRUNC (SYSDATE, 'MONTH'), -1 * LEVEL) AS MO
    , 0 AS DOWNTIME FROM DUAL
     CONNECT BY LEVEL <= 12),
*/
D AS (  -- data simulating a downtime day
     SELECT 'Target Up' AS AVAILABILITY_STATUS,
            TO_DATE ('9/25/2015 15:12:47', 'MM/DD/YYYY HH24:MI:SS')
               AS SINCE,
            385392 AS MINUTES
       FROM DUAL
     UNION ALL
     SELECT 'Target Down' AS AVAILABILITY_STATUS,
            TO_DATE ('11/25/2015 15:12:00', 'MM/DD/YYYY HH24:MI:SS')
               AS SINCE,
            1440 AS MINUTES
       FROM DUAL
     UNION ALL
     SELECT 'Target Up' AS AVAILABILITY_STATUS,
            TO_DATE ('11/26/2015 15:12:00', 'MM/DD/YYYY HH24:MI:SS')
               AS SINCE,
            200122 AS MINUTES
       FROM DUAL)
SELECT *
FROM D
   PIVOT
      (SUM (MINUTES)
      AS TIME
      FOR AVAILABILITY_STATUS
      IN ('Target Up' AS UP,
         'Target Down' AS DOWN,
         'Blackout' AS BLACKOUT));

The result now looks like this:

SINCE                  UP_TIME          DOWN_TIME   BLACKOUT_TIME                          
 9/25/2015 3:12:47 PM   385,392 
11/25/2015 3:12:00 PM                   1,440 
11/26/2015 3:12:00 PM   200,122 

but I need it to look like this:

MO         DOWN_MINUTES
 3/1/2016     0
 2/1/2016     0
 1/1/2016     0
12/1/2015     0
11/1/2015  1440
10/1/2015     0
 9/1/2015     0
 8/1/2015     0
 7/1/2015     0
 6/1/2015     0
 5/1/2015     0
 4/1/2015     0

P.S.: For the benefit of the group, the actual downtime in query "M" is generated by the following query, which reads from Oracle Enterprise Manager:

WITH X
 AS (SELECT START_TIMESTAMP,
            NVL (END_TIMESTAMP, SYSDATE) AS END_TIMESTAMP,
            AVAILABILITY_STATUS,
            TRUNC (
               (NVL (END_TIMESTAMP, SYSDATE) - START_TIMESTAMP) * 24 * 60)
               MINUTES
       FROM MGMT$AVAILABILITY_HISTORY
      WHERE     AVAILABILITY_STATUS IN
                   ('Target Down', 'Target Up', 'Blackout')
  )
  SELECT AVAILABILITY_STATUS,
     MIN (START_TIMESTAMP) AS SINCE,
     SUM (MINUTES) AS MINUTES
  FROM X
GROUP BY AVAILABILITY_STATUS
ORDER BY MIN (START_TIMESTAMP);

Thank you in advance. I have been spinning my wheels on this for days and it's time to ask for help.

SMerrill8
  • 528
  • 4
  • 12

1 Answers1

1

try this:

WITH 
M AS (  
    SELECT ADD_MONTHS (TRUNC (SYSDATE, 'MONTH'), -1 * LEVEL) AS MO
    , 0 AS DOWNTIME FROM DUAL
    CONNECT BY LEVEL <= 12),

D AS (  -- data simulating a downtime day
     SELECT 'Target Up' AS AVAILABILITY_STATUS,
            TO_DATE ('9/25/2015 15:12:47', 'MM/DD/YYYY HH24:MI:SS')
               AS SINCE,
            385392 AS MINUTES
       FROM DUAL
     UNION ALL
     SELECT 'Target Down' AS AVAILABILITY_STATUS,
            TO_DATE ('11/25/2015 15:12:00', 'MM/DD/YYYY HH24:MI:SS')
               AS SINCE,
            1440 AS MINUTES
       FROM DUAL
     UNION ALL
     SELECT 'Target Up' AS AVAILABILITY_STATUS,
            TO_DATE ('11/26/2015 15:12:00', 'MM/DD/YYYY HH24:MI:SS')
               AS SINCE,
            200122 AS MINUTES
       FROM DUAL)
SELECT M.mo, Nvl(s, 0) AS minutes
FROM M
     LEFT JOIN (  SELECT TRUNC (SINCE, 'MONTH') AS D, SUM (MINUTES) AS S
                    FROM D
                   WHERE AVAILABILITY_STATUS = 'Target Down'
                GROUP BY TRUNC (SINCE, 'MONTH')) GR
        ON GR.D = M.MO
ORDER BY 1;
SMerrill8
  • 528
  • 4
  • 12
Adam Silenko
  • 3,025
  • 1
  • 14
  • 30