2017-08-21 3 views
0

Ich habe Tabelle mit Daten der Ereignisse enthält zwei Daten: 1) Ereignis Startdatum (z. B. 2017-03-01 05:30:00) 2) Event End Datum (. zB 2017-03-01 06:10:00)Count Dauer von Ereignissen und Gruppen in 24 Stunden Intervallen SQL

ich erstellen müssen Bericht mit Struktur, wo Daten Summe alle Ereignisse in bestimmten Jahr-Tag und die Stunde gruppiert in 24-Stunden-Zeitintervall, wie folgt aus:

Zwei Reihen:

Id  | Start date  | End date 
Event 1 | 2017-03-01 07:45 | 2017-03-01 08:15 
Event 2 | 2017-03-01 08:25 | 2017-03-01 08:40 

und Ergebnis Abfrage:

Year-Month-Day | Hours | (Activity time in seconds or minutes - here minutes) 
2017-03-01  | 00 | 0 
2017-03-01  | 01 | 0 
2017-03-01  | 02 | 0 
2017-03-01  | 03 | 0 
2017-03-01  | 04 | 0 
2017-03-01  | 05 | 0 
2017-03-01  | 06 | 0 
2017-03-01  | 07 | 15 
2017-03-01  | 08 | 30 
2017-03-01  | 09 | 00 
... 

Ist elegante Möglichkeit, dies in Oracle SQL zu tun? Ich habe im ersten Moment einen Psudocode geschrieben (wo ich Unterschiede zwischen Anfangs- und Endzeit zähle, überprüfe, wie viele Stunden davon betroffen waren, und dem richtigen Intervall zuweisen), aber vielleicht nativere und leistungsfähigere Lösungen - wie Aggregatfunktionen oder etc?

Danke für Hilfe.

+0

haben Sie die Suchfunktion hier versucht? es gibt viele Antworten zu diesem Thema –

+0

Sicher, aber alle fundierten Antworten konzentrieren sich auf das Zählen von Ereignissen im Intervall, nicht zählen Ereignisdauer in 24h-Intervall-Tabelle in reinem SQL. – wukkie

+0

@TimBiegeleisen Warum 55 Minuten? 07-08 => 15 Minuten (07:45 - 08:00 [E1]) 08-09 => 30 Minuten (08:00 - 08:15 [E1] + 08:25: - 08:40 [E2 ]) – wukkie

Antwort

2

Hier ist eine Abfrage, die das tut, was Sie brauchen. Beachten Sie jedoch, dass dies nur für Ereignisse funktioniert, die in 1 Million Minuten, also etwa 2 Jahren, enden.

WITH event 
    AS (SELECT 'Event 1' AS id, 
       '2017-03-01 07:45' AS start_date, 
       '2017-03-01 08:15' AS end_date 
     FROM DUAL 
     UNION ALL 
     SELECT 'Event 2' AS id, 
       '2017-03-01 08:25' AS start_date, 
       '2017-03-01 08:40' AS end_date 
     FROM DUAL), 
    add_mins 
    AS (SELECT LEVEL 
       - 1 
        AS add_min 
     FROM DUAL 
     CONNECT BY LEVEL <= 1000000), 
    hrs_in_day 
    AS (SELECT LEVEL 
       - 1 
        AS hr 
     FROM DUAL 
     CONNECT BY LEVEL <= 24), 
    all_days_hrs 
    AS (SELECT * 
     FROM (SELECT TO_CHAR (
          (first_start_day 
          + LEVEL 
          - 1), 
          'YYYY-MM-DD' 
         ) 
          AS curr_day 
       FROM (SELECT MIN (curr_day) AS first_start_day, 
           MAX (curr_day) AS last_end_day 
         FROM (SELECT TO_TIMESTAMP (start_date, 'YYYY-MM-DD HH24:MI') 
              AS curr_day 
           FROM event 
           UNION 
           SELECT TO_TIMESTAMP (end_date, 'YYYY-MM-DD HH24:MI') 
              AS curr_day 
           FROM event)) 
       CONNECT BY (first_start_day 
          + LEVEL 
          - 1) < last_end_day), 
       hrs_in_day) 
SELECT hl.curr_day AS year_month_day, 
     LPAD (hl.hr, 2, '0') AS hours, 
     COUNT (h.curr_hr) AS activity_duration_in_min 
FROM all_days_hrs hl 
     LEFT JOIN 
     (SELECT id, 
       start_time, 
       end_time, 
       curr_time, 
       TO_CHAR (curr_time, 'YYYY-MM-DD') AS year_month_day, 
       EXTRACT (HOUR FROM curr_time) AS curr_hr 
     FROM (SELECT id, 
         start_time, 
         end_time, 
         b.add_min, 
         start_time 
         + NUMTODSINTERVAL (b.add_min, 'minute') 
          AS curr_time 
       FROM (SELECT id, 
           start_time, 
           end_time, 
           EXTRACT (DAY FROM dur_interval) * 1440 
           + EXTRACT (HOUR FROM dur_interval) * 60 
           + EXTRACT (MINUTE FROM dur_interval) 
            AS duration_in_min 
         FROM (SELECT id, 
             start_time, 
             end_time, 
             (end_time 
             - start_time) 
              AS dur_interval 
           FROM (SELECT id, 
               TO_TIMESTAMP (
                start_date, 
                'YYYY-MM-DD HH24:MI' 
               ) 
                AS start_time, 
               TO_TIMESTAMP (
                end_date, 
                'YYYY-MM-DD HH24:MI' 
               ) 
                AS end_time 
             FROM event))) a, 
         add_mins b 
       WHERE b.add_min < a.duration_in_min)) h 
      ON (hl.curr_day = h.year_month_day 
       AND hl.hr = h.curr_hr) 
GROUP BY hl.curr_day, 
     hl.hr 
ORDER BY year_month_day NULLS FIRST, 
     hl.hr; 

Es ist ein bisschen langsam, obwohl. Ich habe keine Zeit damit verbracht, über Leistung nachzudenken. Aber es funktioniert. Hier ist die Ausgabe.

Year-Month-day | Hours | Activity_Duration_in_min 
    2017-03-01 | 00 | 0 
    2017-03-01 | 01 | 0 
    2017-03-01 | 02 | 0 
    2017-03-01 | 03 | 0 
    2017-03-01 | 04 | 0 
    2017-03-01 | 05 | 0 
    2017-03-01 | 06 | 0 
    2017-03-01 | 07 | 15 
    2017-03-01 | 08 | 30 
    2017-03-01 | 09 | 0 
    2017-03-01 | 10 | 0 
    2017-03-01 | 11 | 0 
    2017-03-01 | 12 | 0 
    2017-03-01 | 13 | 0 
    2017-03-01 | 14 | 0 
    2017-03-01 | 15 | 0 
    2017-03-01 | 16 | 0 
    2017-03-01 | 17 | 0 
    2017-03-01 | 18 | 0 
    2017-03-01 | 19 | 0 
    2017-03-01 | 20 | 0 
    2017-03-01 | 21 | 0 
    2017-03-01 | 22 | 0 
    2017-03-01 | 23 | 0 

Und wenn wir das Enddatum Event 2 '2017.03.02 (dh das Ereignis dauerte einen Tag und 15 min und 40 min in der 8. Stunde) ändern können wir, dass die Ausgangs Änderungen sehen um die 48 Stunden Dauer zu reflektieren.

Year-Month-day | Hours | Activity_Duration_in_min 
    2017-03-01 | 00 | 0 
    2017-03-01 | 01 | 0 
    2017-03-01 | 02 | 0 
    2017-03-01 | 03 | 0 
    2017-03-01 | 04 | 0 
    2017-03-01 | 05 | 0 
    2017-03-01 | 06 | 0 
    2017-03-01 | 07 | 15 
    2017-03-01 | 08 | 50 
    2017-03-01 | 09 | 60 
    2017-03-01 | 10 | 60 
    2017-03-01 | 11 | 60 
    2017-03-01 | 12 | 60 
    2017-03-01 | 13 | 60 
    2017-03-01 | 14 | 60 
    2017-03-01 | 15 | 60 
    2017-03-01 | 16 | 60 
    2017-03-01 | 17 | 60 
    2017-03-01 | 18 | 60 
    2017-03-01 | 19 | 60 
    2017-03-01 | 20 | 60 
    2017-03-01 | 21 | 60 
    2017-03-01 | 22 | 60 
    2017-03-01 | 23 | 60 
    2017-03-02 | 00 | 60 
    2017-03-02 | 01 | 60 
    2017-03-02 | 02 | 60 
    2017-03-02 | 03 | 60 
    2017-03-02 | 04 | 60 
    2017-03-02 | 05 | 60 
    2017-03-02 | 06 | 60 
    2017-03-02 | 07 | 60 
    2017-03-02 | 08 | 40 
    2017-03-02 | 09 | 0 
    2017-03-02 | 10 | 0 
    2017-03-02 | 11 | 0 
    2017-03-02 | 12 | 0 
    2017-03-02 | 13 | 0 
    2017-03-02 | 14 | 0 
    2017-03-02 | 15 | 0 
    2017-03-02 | 16 | 0 
    2017-03-02 | 17 | 0 
    2017-03-02 | 18 | 0 
    2017-03-02 | 19 | 0 
    2017-03-02 | 20 | 0 
    2017-03-02 | 21 | 0 
    2017-03-02 | 22 | 0 
    2017-03-02 | 23 | 0 
+0

Ich war für eine weitere Möglichkeit testen wo ein Ereignis für mehr als zwei Tage dauern hier wird es keine Tage zeigen, die sind zwischen. Das heißt, wenn wir das Enddatum von "Event 2" auf 2017-03-03 ändern, werden die Einträge für den Tag 2017-03-02 nicht in der Ausgabe angezeigt. –

+0

@Pratikgarg guten Fang! hat den Code aktualisiert. War eine einfache Lösung. –

Verwandte Themen