2010-02-02 8 views
3

J'ai besoin d'aide pour ce que je pense être une requête d'auto-jointure assez simple. Il a juste besoin de combiner l'heure de début de mise en correspondance et de fin de deux enregistrements dans un enregistrementAuto-jointure de données de séries chronologiques

Dire que j'ai ce qui suit dans une table

Time Event 
08:00 Start 
09:00 Stop 
10:30 Start 
10:45 Stop 
11:00 Start 
11:15 Start 
12:00 Stop 
12:30 Stop 

Je veux une vue comme celui-ci

StartTime Stoptime 
08:00 09:00 
10:30 10:45 
11:00 
11:15 12:00 
     12:30 

Notez qu'il devrait trouver l'heure de début ou de fin la plus proche. Si, pour une raison quelconque, il n'y a pas d'événement correspondant, il doit rester vide.

Merci,

+0

Quelque chose est drôle dans vos données et de la production. Vous montrez les événements à partir de 11h00 et 11h15, puis les événements s'arrêtent à 12h00 et 12h30. Ensuite, votre exemple d'affichage affiche les heures de début et de fin des événements: 11h00 et 11h15, puis 12h00 et 12h30 (faute de frappe). Je suppose que ces deux derniers enregistrements devraient être 11h00, 12h00 et 11h15 et 12h30. –

+0

Le 13:30 devrait être 12:30, je l'ai réparé mais ma modification ne s'affiche pas pour une raison quelconque. L'heure de début et l'heure de fin qui doivent être rapprochées doivent toujours être les plus proches, ensemble, dans le temps. En de rares occasions, le système ne peut pas enregistrer une heure de début ou de fin pour un événement. – Automate

+0

Avoir une dépendance d'ordre au niveau de la ligne est une violation de 1NF, la meilleure chose à faire avec n'importe quel niveau de santé mentale est de faire correspondre une heure de début avec l'heure de fin disponible suivante. Cela mettrait 11:00 Début/12:00 Fin, 11:15 Début, 13:30 Terminer. Vous devriez mettre une description de tâche unique dans les données afin que votre clé primaire soit (tâche, événement) –

Répondre

4

Avertissement: Je songerais sérieusement à une conception de table différente. Rejoindre des dates et/ou des heures n'est jamais une bonne idée. Si vous aviez un ID de l'événement qui démarre, vous pourriez facilement LEFT JOIN pour essayer de trouver la fin correspondante de cet événement.

Pour essayer SQL Server:

DECLARE @Events table (EventTime char(5), EventType varchar(5)) 

INSERT INTO @Events VALUES ('08:00','Start') 
INSERT INTO @Events VALUES ('09:00','Stop') 
INSERT INTO @Events VALUES ('10:30','Start') 
INSERT INTO @Events VALUES ('10:45','Stop') 
INSERT INTO @Events VALUES ('11:00','Start') 
INSERT INTO @Events VALUES ('11:15','Start') 
INSERT INTO @Events VALUES ('12:00','Stop') 
INSERT INTO @Events VALUES ('12:30','Stop') 

SELECT 
    dt.StartTime, dt.StopTime 
    FROM (SELECT 
       p.EventTime AS StartTime,CASE WHEN c.EventType!='Stop' THEN NULL ELSE c.EventTime END AS StopTime 
        ,p.EventTime AS SortBy 
       FROM @Events   p 
       INNER JOIN @Events c ON p.EventTime<c.EventTime 
       WHERE p.EventType='Start' 
        AND c.EventTime=(SELECT MIN(EventTime) FROM @Events WHERE EventTime>p.EventTime) 
      UNION 
      SELECT 
       NULL AS StartTime,p.EventTime 
        ,p.EventTime AS SortBy 
       FROM @Events   p 
       INNER JOIN @Events c ON p.EventTime>c.EventTime 
       WHERE p.EventType='STOP' 
        AND c.EventTime=(SELECT MAX(EventTime) FROM @Events WHERE EventTime<p.EventTime) 
        AND c.EventType='Stop' 
     ) dt 
    ORDER BY dt.SortBy 

SORTIE:

StartTime StopTime 
--------- -------- 
08:00  09:00 
10:30  10:45 
11:00  NULL 
11:15  12:00 
NULL  12:30 

(5 row(s) affected) 
+0

Merci pour la solution. Dans ce cas, les données sont enregistrées par un paquet tiers sur lequel je n'ai aucun contrôle, donc elles n'ont pas de champ ID pour lier les événements. J'essaie juste d'afficher les événements dans un format plus significatif. – Automate

0

Je devine que vous utilisez la balise SQL signifie sql-server. Mais dans le cas où les futurs demandeurs sont intéressés par une solution Oracle ce problème peut être résolu avec les LEAD() et LAG() analytiques fonctions ...

SQL> select * from (
    2  select case when event = 'Start' then t else null end as start_t 
    3    , case when next_event = 'Stop' then next_t 
    4     when event = 'Stop' and prev_event = 'Stop' then next_t 
    5     else null end as stop_t 
    6  from (
    7   select event 
    8     , t 
    9     , lead (t) over (order by t) as next_t 
10     , lead (event) over (order by t) as next_event 
11     , lag (event) over (order by t) as prev_event 
12   from t23 
13   order by t) 
14  ) 
15 where start_t is not null 
16 or stop_t is not null 
17/

START STOP_ 
----- ----- 
08:00 09:00 
10:30 10:45 
11:00 
11:15 12:00 
     12:30 

SQL> 
Questions connexes