我有一个包含如下数据的表,想要返回具有唯一数据的那些 group_id。group_id 3 和 4 都有两个分量 123 和 456,所以它们是“重复的”,我们只需要返回较小的 group_id,即 3。另外 group_id 5 没有重复,可以返回。所以我们希望返回 group_id 3 和 5。
如何针对 postgres 数据库编写 SQL 查询来实现这一点?谢谢!
| ID | group_id | 组件标识 |
|---|---|---|
| 1 | 3 | 123 |
| 2 | 3 | 456 |
| 3 | 4 | 123 |
| 4 | 4 | 456 |
| 5 | 5 | 123 |
我有一个包含如下数据的表,想要返回具有唯一数据的那些 group_id。group_id 3 和 4 都有两个分量 123 和 456,所以它们是“重复的”,我们只需要返回较小的 group_id,即 3。另外 group_id 5 没有重复,可以返回。所以我们希望返回 group_id 3 和 5。
如何针对 postgres 数据库编写 SQL 查询来实现这一点?谢谢!
| ID | group_id | 组件标识 |
|---|---|---|
| 1 | 3 | 123 |
| 2 | 3 | 456 |
| 3 | 4 | 123 |
| 4 | 4 | 456 |
| 5 | 5 | 123 |
SELECT group_id, MIN(component_id)
FROM MyTable
GROUP BY group_id
HAVING COUNT(*) > 1
这是将 group_id 分配给 component_id 的方法。
它使用带有数组的递归 CTE 来查找可能的组合。
递归从孤独的 group_id 开始。
然后下一个 CTE 选择最长的组合之一。
WITH RECURSIVE RCTE AS ( SELECT id, group_id, component_id , 1 as Lvl , array[group_id] as group_ids , array[component_id] as component_ids FROM YourTable WHERE group_id IN ( SELECT group_id FROM YourTable GROUP BY group_id HAVING COUNT(*) = 1 ) UNION ALL SELECT t.id, t.group_id, t.component_id , Lvl+1 , cte.group_ids || t.group_id , cte.component_ids || t.component_id FROM RCTE cte JOIN YourTable t ON t.group_id != ALL(group_ids) AND t.component_id != ALL(component_ids) ) , CTE_ARRAYS AS ( SELECT group_ids, component_ids FROM RCTE ORDER BY array_length(group_ids, 1) desc, Lvl desc LIMIT 1 ) SELECT a.group_id, a.component_id FROM CTE_ARRAYS c CROSS JOIN LATERAL UNNEST(c.group_ids, c.component_ids) WITH ORDINALITY AS a(group_id, component_id) ORDER BY a.group_id;
| group_id | 组件标识 |
|---|---|
| 3 | 456 |
| 5 | 123 |
db<>在这里摆弄
使用 2 级聚合:
SELECT MIN(group_id) group_id
FROM (
SELECT group_id, STRING_AGG(component_id::text, ',' ORDER BY component_id) components
FROM tablename
GROUP BY group_id
) t
GROUP BY components;
请参阅演示。