SQL - 对于表中的每个条目 - 检查关联的行

时间:2017-05-11 14:19:48

标签: sql sql-server

我有一个日志表,记录特定事件的起始行和结束行。

每个事件都应该有一个开始行,如果一切正常,它应该有一个结束行。

但如果出现问题,则可能无法创建结束行。

我希望SELECT表中包含起始行但不是相关结束行的所有内容。

例如,考虑如下表:

id  event_id  event_status
1     123           1
2     123           2
3     234           1
4     234           2
5     456           1
6     678           1
7     678           2

请注意,id列5有一个起始行但没有结束行。 Start是event_status为1,end是event_status为2。

如何撤回所有具有起始行但不是结束行>的event_ids?

这是针对mssql的。

3 个答案:

答案 0 :(得分:4)

您可以使用not exists子查询来要求不存在结束事件的其他行:

select  *
from    YourTable t1
where   status = 1
        and not exists
        (
        select  *
        from    YourTable t2
        where   t2.event_id = t1.event_id
                and t2.status = 2
        )

答案 1 :(得分:0)

您可以尝试使用左连接,如下所示:

select y1.event_id from #yourevents y1 left join #yourevents y2
    on y1.event_id = y2.event_id
    and y1.event_status = 1
    and y2.event_status = 2
    where y2.event_id is null
        and y1.event_status = 1

答案 2 :(得分:0)

在这种特殊情况下,您可以使用以下三种解决方案之一:

解决方案1.经典
检查是否没有结束状态

SELECT * 
FROM myTable t1 
WHERE NOT EXISTS (
    SELECT * 
    FROM myTable t2 
    WHERE t1.event_id = t2.event_id AND t2.status=2
)

解决方案2.让它漂亮。不要做那么多括号的子查询
相同的检查,但更简洁和漂亮的方式

SELECT t1.*
FROM myTable t1
LEFT JOIN myTable t2 ON t1.event_id = t2.event_id AND t2.status=2
-- Doesn't exist
WHERE t2.event_id IS NULL

解决方案3.查找每个事件的最后状态
在状态逻辑变得更复杂的情况下具有更大的灵活性

WITH last_status AS (
SELECT
  id,
  event_id,
  status,
  -- The ROWS BETWEEN ..yadda yadda ... FOLLOWING might be unnecessary. Try, check.
  last_value(status) OVER (PARTITION BY event_id ORDER BY status ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_status
FROM myTable 
)
SELECT
  id,
  event_id,
  status
FROM last_events
WHERE last_status<>2

还有更多,有最小/最大查询和其他。选择最适合您的清洁度,可读性和多功能性的产品。