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

SQL-针对表中的每个条目-检查关联行,sql,sql-server,Sql,Sql Server,我有一个日志表,记录特定事件的开始行和结束行 每个事件都应该有一个开始行,如果一切正常,它应该有一个结束行 但如果出现问题,则可能无法创建结束行 我想选择表中有起始行但没有关联结束行的所有内容 例如,考虑这样的表: id event_id event_status 1 123 1 2 123 2 3 234 1 4 234 2 5 456 1 6

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

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

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

我想选择表中有起始行但没有关联结束行的所有内容

例如,考虑这样的表:

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有一个起始行,但没有结束行。开始是事件状态1,结束是事件状态2

如何收回所有具有开始行但没有结束行的事件标识>

这是针对mssql的。

您可以使用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
        )
您可以使用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
        )

您可以按如下方式尝试使用左自联接:

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

您可以按如下方式尝试使用左自联接:

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

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

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

还有更多,包括最小/最大查询和其他查询。选择最适合您的清洁度、可读性和多功能性要求的解决方案。

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

解决方案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
还有更多,包括最小/最大查询和其他查询。选择最适合您的清洁度、可读性和多功能性需求的产品