PostgreSQL获取两列用户ID唯一组合数据问题求助
解决方案
要实现按id降序筛选出不包含已出现过的user_id的行,最终得到id=51353和id=51350的记录,可以使用递归CTE逐步跟踪已出现的用户ID集合,具体SQL如下:
WITH RECURSIVE sorted_rows AS ( -- 按id降序排序并分配行号,确保处理顺序正确 SELECT id, user_id_1, user_id_2, ROW_NUMBER() OVER (ORDER BY id DESC) AS rn FROM time_user ), selected_rows AS ( -- 初始行:取id最大的记录,初始化已出现用户集合 SELECT id, user_id_1, user_id_2, rn, ARRAY[user_id_1, user_id_2] AS seen_users FROM sorted_rows WHERE rn = 1 UNION ALL -- 递归处理后续行:仅选中两个用户ID均未出现过的记录 SELECT sr.id, sr.user_id_1, sr.user_id_2, sr.rn, sr_seen.seen_users || ARRAY[sr.user_id_1, sr.user_id_2] AS seen_users FROM sorted_rows sr JOIN selected_rows sr_seen ON sr.rn = sr_seen.rn + 1 WHERE sr.user_id_1 <> ALL(sr_seen.seen_users) AND sr.user_id_2 <> ALL(sr_seen.seen_users) ) -- 输出最终选中的记录 SELECT id, user_id_1, user_id_2 FROM selected_rows;
执行逻辑说明
- sorted_rows CTE:将
time_user表的所有记录按id降序排列,同时为每行分配一个连续的行号rn,保证后续按从大到小的顺序处理记录。 - selected_rows 递归CTE:
- 初始阶段:选中行号为1的记录(即
id=51353),并将该行的user_id_1和user_id_2存入数组seen_users,作为已出现的用户ID集合。 - 递归阶段:依次处理下一行(行号=上一行行号+1),检查当前行的两个用户ID是否都不在
seen_users数组中。如果均未出现,则选中该行,并将这两个用户ID追加到seen_users数组中;如果任一用户ID已存在,则跳过该行。
- 初始阶段:选中行号为1的记录(即
- 最终查询从
selected_rows中提取所需字段,得到符合需求的记录。
验证结果
执行上述SQL后,将返回以下两条记录:
| id | user_id_1 | user_id_2 |
|---|---|---|
| 51353 | 21014 | 21013 |
| 51350 | 21010 | 21011 |
内容的提问来源于stack exchange,提问作者Vit
相关产品推荐
相关产品推荐

