【问题标题】:SQL Query for events that happend in a specific order以特定顺序发生的事件的 SQL 查询
【发布时间】:2016-09-30 06:34:16
【问题描述】:

我有下表:

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

我的目标是获取所有同时具有事件 A 和 B 的对象,条件是 A 先发生(及时)。到目前为止,我只提出了一个查询来找到所有具有 A 和 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

因为这是唯一满足所有条件的对象。

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

感谢您的帮助

【问题讨论】:

  • 我正在使用 Vertica。我知道有诸如 LAG 和 LEAD 之类的功能,但我想看看是否有通用方法。另外,我仍然不是 100% 如何在我的案例中使用 LAG 和 LEAD :)

标签: sql vertica


【解决方案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'

【讨论】:

  • 我仍在试图了解这里发生了什么,但这似乎有效。非常感谢。
【解决方案2】:

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

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

MySQL 演示:

SQLFiddle

【讨论】:

  • 你在哪里定义Object必须有事件B?
  • 条件t1.Event &lt;&gt; 'A' 将覆盖另一个记录是事件B。如果COUNT 为2,则表示它有AB。如果您有两个以上的事件,这也将起作用。
  • 我不明白,所以如果我有多个事件(例如 A、B、C)并且我只想要按顺序只有事件 A 和 B 的对象,这将如何工作?
  • 它可能无法涵盖所有​​情况。但是例如,如果您首先想要A,并且同时存在BC,您只需将计数更改为3,我的查询就可以工作。无论如何,它绝对可以解决您的问题。
  • 您是否费心尝试我设置的演示?
【解决方案3】:

试试这个:

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

【讨论】:

    【解决方案4】:

    如果您使用的是 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
    

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        猜你喜欢
        • 2022-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-08
        相关资源
        最近更新 更多