2011-07-14 3 views
1

J'ai source de données dans le format suivant:Oracle - aider à faire une requête

Event Type| Date 
1   | 2011-07-14 09:00 
1   | 2011-07-14 09:01 
1   | 2011-07-14 09:02 
2   | 2011-07-14 09:30 
2   | 2011-07-14 09:31 
1   | 2011-07-14 10:00 
1   | 2011-07-14 10:01 

types d'événements sont classés par date, comme ils se sont produits. J'ai besoin de faire une requête qui montrera les plages de dates lorsque les événements ont été utilisés, triés par date. Comme ceci:

Event Type | Date Range 
1   | 2011-07-14 09:00 - 2011-07-14 09:02 
2   | 2011-07-14 09:30 - 2011-07-14 09:31 
1   | 2011-07-14 10:00 - 2011-07-14 10:01 

Avez-vous des indices? Je pense que cela devra probablement être fait avec des fonctions analytiques, mais je n'ai pas encore réussi à trouver une solution décente.

+1

Pourquoi le type d'événement 1 indiqué deux fois dans la sortie? La sortie est-elle supposée être groupée par heure? – Jay

+1

Il est groupé par des événements consécutifs ayant le même type d'événement, puis trouvant le premier et le dernier événement du groupe. Le deuxième enregistrement pour event_type 1 est celui où il y a un event_type 1 * après * un événement qui n'était pas event_type 1. – MatBailie

Répondre

2

Vous pouvez également essayer l'approche suivante:

WITH ranked AS (
    SELECT 
    EventType, 
    Date, 
    ROW_NUMBER() OVER (ORDER BY Date) - 
     ROW_NUMBER() OVER (PARTITION BY EventType ORDER BY Date) AS GroupID 
    FROM Events 
) 
SELECT 
    EventType, 
    MIN(Date) AS StartDate, 
    MAX(Date) AS EndDate 
FROM ranked 
GROUP BY 
    GroupID, 
    EventType 
ORDER BY 
    MIN(Date) 
+0

Bonne réflexion! Merci! – Dario

1

Je suis sûr qu'il existe une meilleure solution, mais qu'en est-il de cela?

WITH 
    ordered_data AS 
(
    SELECT ROW_NUMBER() OVER (ORDER BY Date) AS row_id, * FROM event_data 
), 
    [start_events] AS 
(
    SELECT * FROM ordered_data AS [start] 
    WHERE NOT EXISTS (SELECT * FROM ordered_data WHERE row_id = [start].row_id - 1 AND event_type = [start].event_type) 
), 
    [end_events] AS 
(
    SELECT * FROM ordered_data AS [end] 
    WHERE NOT EXISTS (SELECT * FROM ordered_data WHERE row_id = [end].row_id + 1 AND event_type = [end].event_type) 
) 

SELECT 
    * 
FROM 
    [start_events] 
INNER JOIN 
    [end_events] 
    ON [end_events].row_id = (SELECT MIN(row_id) FROM [end_events] WHERE row_id >= [start_events].row_id) 

Cela devrait également faire face à des scénarios où le 'groupe' n'a qu'un seul événement; Tels que (1, 1, 2, 1, 1)