获取没有“结束”事件的行

Ban*_*San 1 t-sql

我有一系列代表 start ( S) 或 and ( E) 的行thing

+----+-------+-------+
| Id | Event | Thing |
+----+-------+-------+
|  1 | S     | A     |
|  2 | E     | A     |
|  3 | S     | B     |
|  4 | E     | B     |
|  5 | S     | C     |
|  6 | S     | D     |
|  7 | S     | E     |
+----+-------+-------+
Run Code Online (Sandbox Code Playgroud)

我正在尝试获取没有结束事件的行。

SELECT [a].[Id] AS [ID a],
       [a].[Event] AS [Event a],
       [b].[Id] AS [ID b],
       [b].[Event] AS [Event b]
  FROM [dbo].[TimeSeries] AS [a]
  LEFT OUTER JOIN [dbo].[TimeSeries] AS [b]
    ON [b].[Thing] = [a].[Thing]
   WHERE [a].[Event] = 'S'
   AND [b].[Event] = 'E'
Run Code Online (Sandbox Code Playgroud)

这返回

+------+---------+------+---------+
| ID a | Event a | ID b | Event b |
+------+---------+------+---------+
|    1 | S       |    2 | E       |
|    3 | S       |    4 | E       |
+------+---------+------+---------+
Run Code Online (Sandbox Code Playgroud)

这就是我陷入困境的地方。

我想要所有既不在ID a列中也不在ID b列中的 ID 。然后我猜想LEFT JOIN找到所有没有结束事件的行。

注意:真正的表是一个包含数百万行的 SSIS 日志。

Mar*_*ith 5

这里有几个方法。

  1. 使用NOT EXISTS 了防半加盟
SELECT Id,
       Event,
       Thing
FROM   dbo.TimeSeries t1
WHERE  NOT EXISTS(SELECT *
                  FROM   dbo.TimeSeries t2
                  WHERE  t1.Thing = t2.Thing
                         AND t2.Event = 'E');
Run Code Online (Sandbox Code Playgroud)
  1. 事物分区并找到每个分区中的最小(按字母顺序排列)事件。如果是S而不是E这个Thing没有结束事件。
WITH T
     AS (SELECT *,
                MIN(Event) OVER (PARTITION BY Thing) AS Evt
         FROM   dbo.TimeSeries
         WHERE  Event IN ( 'E', 'S' ))
SELECT Id,
       Event,
       Thing
FROM   T
WHERE  Evt = 'S';
Run Code Online (Sandbox Code Playgroud)
  1. 事物分区并LAG在按事件字母顺序排序时用于查看前一行到当前行。如果当前行是S并且没有前一行Evt将是NULL。只需保留任何此类行。这是 2012+ 语法。
WITH T
     AS (SELECT *,
                LAG(Event) OVER (PARTITION BY Thing ORDER BY Event) AS Evt
         FROM   dbo.TimeSeries
         WHERE  Event IN ( 'E', 'S' ))
SELECT Id,
       Event,
       Thing
FROM   T
WHERE  Event = 'S' AND Evt IS NULL;
Run Code Online (Sandbox Code Playgroud)