如何在每个id只有一个初始行的SQL筛选行中进行筛选?

如何在每个id只有一个初始行的SQL筛选行中进行筛选?,sql,postgresql,Sql,Postgresql,我有一个id和状态都只被写入的表,从不更新,我只想查询具有初始状态的id,也就是说,只有第一行被写入的id的行,这样我就可以处理这些行的状态更改。 如果处理进展顺利,将为这些id写入一个新状态,下次查询时,我不应获取已成功处理的id为的行 示例:我有两行表示状态为“INITIAL”和“DONE”的id,另一行表示状态为“INITIAL”的第二个id。 当我查询时,我只想得到第二个id 我尝试过使用GroupBy,但由于我无法在不分组的情况下对状态进行筛选,因此它没有按照我的预期工作 我提出了这个

我有一个id和状态都只被写入的表,从不更新,我只想查询具有初始状态的id,也就是说,只有第一行被写入的id的行,这样我就可以处理这些行的状态更改。 如果处理进展顺利,将为这些id写入一个新状态,下次查询时,我不应获取已成功处理的id为的行

示例:我有两行表示状态为“INITIAL”和“DONE”的id,另一行表示状态为“INITIAL”的第二个id。 当我查询时,我只想得到第二个id

我尝试过使用GroupBy,但由于我无法在不分组的情况下对状态进行筛选,因此它没有按照我的预期工作

我提出了这个问题,但这真的是解决问题的方法吗

select id, state from states s1 where state = 'INITIAL' and not exists
(select 1 from states s2 where s2.state != 'INITIAL' and s2.id = s1.id);
我正在使用Postgres顺便说一句:

我在这里发现了许多类似的问题,但不完全是这个问题,但如果你知道的话,请告诉我另一个答案!:


谢谢你的帮助

一个可能是最有效的选项使用NOT EXISTS子句:

我们也可以在这里使用聚合:

SELECT s1.id, s1.state
FROM states s1
INNER JOIN
(
    SELECT id
    FROM states
    GROUP BY id
    HAVING COUNT(CASE WHEN state <> 'INITIAL' THEN 1 END) = 0
) s2
    ON s1.id = s2.id;
另一个选项是自联接:

SELECT s1.id, s1.state
FROM states s1
LEFT JOIN states s2
    ON s1.id = s2.id AND s2.state <> 'INITIAL'
WHERE s1.state = 'INITIAL' AND s2.id IS NULL;

此查询的工作原理是保留id为初始的所有记录,但不能连接到具有相同id且状态不是初始的另一条记录。

因为初始状态是第一个状态,所以我使用count仅选择了一行id

SELECT id
FROM (SELECT id, state, COUNT(*) count
      FROM states
      GROUP BY id) as c
WHERE c.count = 1 
  AND c.state = 'INITIAL'
使用有cluase

select id from states s1 
group by id
having sum(case when state='INITIAL' then 1 else 0 end)=1
and sum(case when state<>'INITIAL' then 1 else 0 end)=0

我认为您不需要检查是否存在首字母,因为如果排除所有非首字母的记录,并且仍然存在一个组,则意味着剩余的记录是首字母。第一个记录与我的尝试相同,对吗?:但是谢谢!我喜欢这个箱子。那是专为博士后准备的吗?@ChillyPro我想我没有把你的问题读清楚。第二个选项应该在几乎所有SQL数据库上运行。你用哪个版本真的取决于你;我认为这两个行应该有相似的性能。谢谢,但我不喜欢在这里不检查状态名称,以防某些错误或人为错误删除初始行,或者它从未被写入。@ChillyPro state添加
select id from states s1 
group by id
having sum(case when state='INITIAL' then 1 else 0 end)=1
and sum(case when state<>'INITIAL' then 1 else 0 end)=0