3 votes

Requête SQL pour les événements qui se sont produits dans un ordre spécifique

J'ai le tableau suivant :

+--------+-------+------+--+
| Object | Event | Time |  |
+--------+-------+------+--+
| Obj1   | A     |    1 |  |
| Obj1   | B     |    3 |  |
| Obj2   | A     |    7 |  |
| Obj2   | B     |    4 |  |
+--------+-------+------+--+

Mon but est d'obtenir tous les objets qui ont tous deux eu l'événement A & B avec la condition que A se soit produit en premier (dans le temps). Jusqu'à présent, je n'ai trouvé que la requête permettant de trouver tous les objets qui ont eu A et B sans inclure le temps :

SELECT DISTINCT Object 
FROM
    (SELECT * 
     FROM
         (SELECT * 
          FROM table
          INNER JOIN 
              (SELECT Object Obj 
               FROM table 
               WHERE event LIKE '%A%' AS temp_table) ON table.Object = temp_table.Obj) AS temp_final 
     WHERE event LIKE '%B%') AS temp2;

Donc le résultat final serait que j'obtienne un tableau qui inclut seulement :

Obj1

Puisque c'est le seul objet qui remplit tous les critères.

La colonne de temps est un timbre de date dans la vie réelle, mais pour la simplicité j'ai utilisé des entiers.

Merci pour votre aide

1voto

Tim Biegeleisen Points 53335

Voici une solution compacte qui devrait fonctionner sur la plupart des SGBDR. Cette solution ne suppose pas qu'il n'y ait que deux événements, et devrait fonctionner pour n'importe quel nombre d'événements.

SELECT t1.Object
FROM yourTable t1
INNER JOIN
(
    SELECT Object, MIN(Time) AS Time
    FROM yourTable
    GROUP BY Object
) t2
    ON t1.Object = t2.Object AND
       ((t1.Event = 'A' AND t1.Time = t2.Time) OR
        t1.Event <> 'A')
GROUP BY t1.Object
HAVING COUNT(*) = 2    -- change this count to match # of events

Démonstration sur MySQL :

SQLFiddle

1voto

Radu Gheorghiu Points 3332

Si vous ne suivez que deux événements qui se sont produits l'un après l'autre, vous pouvez résoudre ce problème avec un seul fichier JOIN .

Cela fonctionnera quel que soit le nombre d'événements Obj1 a, comme vous l'avez mentionné, vous êtes seulement intéressé par A y B existant et étant l'un après l'autre, respectivement.

select distinct t1.object
from TABLE t1
    inner join TABLE t2 on t1.object = t2.object
        and t2.time > t1.time
        and t1.event = 'A'
        and t2.event = 'B'

Voici un exemple du résultat de ce code :

declare @tbl table (obj varchar(10), event varchar(1), time int)

insert @tbl values ('Obj1', 'A', 1), ('Obj1', 'B', 3), ('Obj2', 'A', 7), ('Obj2', 'B', 4)

select distinct t1.obj
from @tbl t1
    inner join @tbl t2 on t1.obj = t2.obj
        and t2.time > t1.time
        and t1.event = 'A'
        and t2.event = 'B'

0voto

Joe Taras Points 4050

Essayez ça :

SELECT DISTINCT object
FROM yourtable t
WHERE EXISTS
    (SELECT FROM yourtable t3
    WHERE t3.object = t.object
    AND t3.event = 'A'
    AND EXISTS
        (SELECT 'B'
        FROM yourtbale t4
        WHERE t4.object = t3.object
        AND t4.event = 'B'
        AND t4.time > t3.time)
   )

0voto

Tedo G. Points 1092

Si vous utilisez sql-server :

SELECT
      A.[Object]
    , A.[Time]
    , B.[Time]
FROM
    (SELECT 
        Distinct [Object]
    FROM
        [table] AS A
    WHERE
        A.[Event] = 'A'
    ) AS A
        CROSS APPLY
    (SELECT
        TOP 1 *
    FROM
        [table] AS B
    WHERE
        [Event] = 'B'
        AND
        B.[Object] = A.[Object]
        AND
        A.[Time] < B.[Time]) AS B

0voto

LeeLep Points 11

Pour SQL Server :

;with A as
(select Object, MIN(Time) as Time from table where Event='A' group by Object)
, B as
(select Object, MIN(Time) aS Time from table where Event='B' group by Object)
Select A.Object from A inner join B on B.Object=A.Object where A.Time < B.Time

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X