2016-09-30 93 views
3

我有如下表:SQL查询,在一个特定的顺序happend事件

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

我的目标是让所有对象均得了事件A & B带的是一个首先发生的条件(在时间)。到目前为止,我只是想出了查询,发现我有一个& B,不含包括时间的所有对象:

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; 

所以,最终的结果将是,我只得到了包括表:

Obj1 

由于这是满足所有标准的唯一对象。

时间列是现实生活中的日期标记,但为了简单起见,我使用了整数。

感谢大家的帮助

+0

我使用Vertica的。我知道有这样的功能,如LAG和LEAD,但我想看看是否有一个通用的方法。另外我还没有100%如何使用LAG和铅为我的情况:) – valenzio

回答

1

如果您只跟踪两个发生的事件,那么您可以用一个JOIN来解决这个问题。

无论Obj1了,你怎么提到的事件的数量这将工作,你只AB现有的和分别为一前一后,有兴趣的。

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' 

这里是代码的结果的一个样本:

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' 
+0

我仍然试图了解这里发生了什么,但这似乎工作。非常感谢。 – valenzio

1

这里是一个要在大多数RDBMS运行一个紧凑的解决方案。此解决方案不会假定只有两个事件,并且应该运行任意数量的事件。在MySQL

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 

演示:

SQLFiddle

+0

你在哪里定义对象必须有事件B? – valenzio

+0

条件't1.Event <>'A''将覆盖事件'B'的另一条记录。如果COUNT是2,那么它表示它有'A'和'B'。如果您有两个以上的事件,这也会起作用。 –

+0

我不明白,所以如果我有多个事件(例如A,B,C),而且我只想要那些只有事件A和B的对象,那么这将如何工作? – valenzio

0

试试这个:

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) 
    ) 
0

如果您使用的是SQL服务器:

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 
0

对于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