获取两个id第一次出现的所有行

问题描述 投票:0回答:1

我需要帮助解决一个让我发疯的问题。
假设您有下表,其中只有三个 ID。
CREATE TABLE candidates
(
    row_num BIGINT,
    in_id  BIGINT,
    out_id BIGINT
);

用一些数据填充它:

INSERT INTO candidates (row_num, in_id, out_id)
VALUES (1, 220, 210),
       (2, 208, 210),
       (3, 216, 210),
       (4, 220, 214),
       (5, 208, 214),
       (6, 216, 214),
       (7, 212, 218);

我现在想要的是以每个

in_id
out_id
在所有选定行中都是唯一的方式选择所有行。
所以我们选择第一行,因为我们之前既没有看到
in_id
220 也没有看到
out_id
210。选择了
(220,210)
对,因此不允许后续行具有
in_id
220 或
out_id
210。这就是为什么我们需要跳过接下来的 3 行(它们要么具有
in_id
220 要么
out_id
210).现在我们以
row_num
5 结束。之前选择的 208 和 214 都没有。这就是为什么它也应该成为最终结果集的一部分。
row_num
7.

也一样

最终结果集应该是这样的:

row_num | in_id | out_id
   1       220      210
   5       208      214
   7       212      218

看起来很简单,但我无法解决。最干净的尝试是以下查询,它有一个问题,尽管它知道在无法检测是否选择了一行之前出现了哪些 ID。

row_num
5.

的中断
SELECT *
FROM candidates tc1
WHERE NOT EXISTS (
  SELECT
  FROM candidates tc2
  WHERE (tc2.in_id = tc1.in_id OR tc2.out_id = tc1.out_id)
    AND tc2.row_num < tc1.row_num
);

非常感谢任何帮助,谢谢!

postgresql postgresql-15
1个回答
0
投票

这可以使用

WITH recursive
来完成:

with recursive cte as (
  select row_num, in_id, out_id, 1 as exist
  from candidates
  where row_num = 1
  union all
  select t.row_num, t.in_id, t.out_id, exist+1
  from cte c
  inner join candidates t on t.row_num > c.row_num
  and (t.in_id <> c.in_id and t.out_id <> c.out_id)
)
select t.row_num, t.in_id, t.out_id
from candidates t
inner join (
  select min(row_num) as row_num, exist
  from cte
  group by exist
) as s on s.row_num = t.row_num

递归 CTE 用于通过将以前的记录与当前表连接起来递归地获取记录,其中当前行大于已找到的记录并且当前的 in_id 和 out_id 在以前的记录中不存在。

这里演示

相关问题
热门问答
最新问题