如何在SQL筛选器行中每个ID仅包含初始行?

时间:2018-10-05 08:16:17

标签: sql postgresql

我有一个只有ID和状态被写入的表,从未更新过,在这里我只想查询具有初始状态的ID,即只有ID为第一行的行,以便我可以对其进行处理状态发生变化。 如果处理正常,则将为这些ID写入新状态,下次我查询时,不应获得ID已成功处理的行。

示例:对于具有状态“ INITIAL”和“ DONE”的ID,我有两行,对于具有状态“ INITIAL”的第二个ID,我有另一行。 当我查询时,我只想获取第二个ID。

我尝试了group by,但是由于我也无法对状态进行过滤,而不对它进行分组,因此它无法按照我的意图工作。

我想出了这个查询,但这真的是如何解决它?

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

我在这里发现了许多类似的问题,但并非完全是这个问题,但是如果您知道一个,请直接将我引向另一个答案! :)

感谢帮助!

3 个答案:

答案 0 :(得分:3)

一个选项,也许是最有效的,使用了NOT EXISTS子句:

SELECT id, state
FROM states s1
WHERE
    state = 'INITIAL' AND
    NOT EXISTS (SELECT 1 FROM states s2 WHERE s1.id = s2.id AND s2.state <> 'INITIAL');

我们也可以在此处使用聚合:

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;

此查询的工作方式是保留idINITIAL的所有记录,但不能与状态为 other 的具有相同id的另一条记录联接INITIAL

答案 1 :(得分:1)

因为INITIAL是第一个状态,所以我只选择了1行(使用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'

答案 2 :(得分:1)

使用具有封闭性的

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