Присвоение id группы для при совпадении хотя бы одного из значений
Нужна помощь, есть набор строк с n идентификаторами, в у некоторых строк они совпадают, нужно для строк в которых хотя бы один из идентификаторов совпадает присвоить общий id ( id группы),. Каждая строка может входить только в одну группу. К примеру в строках 1, 4, 8 совпадает id_a, у 8 и 9 id_b - значит это одна группа. Совпадение только в рамках типа идентификатора , id_a = id_a и т.д.
SELECT 1 row_id, 'a1' id_a, 'b1' id_b, 'c1' id_x, 'd1' id_d
UNION
SELECT 2 , 'a2' id_a, 'b2' id_b, 'c2' id_x, 'd9' id_d
UNION
SELECT 3 , 'a3' id_a, 'b3' id_b, 'c3' id_x, 'd3' id_d
UNION
SELECT 4 , 'a1' id_a, 'b4' id_b, 'c4' id_x, 'd4' id_d
UNION
SELECT 5 , 'a5' id_a, 'b5' id_b, 'c5' id_x, 'd5' id_d
UNION
SELECT 6 , 'a6' id_a, 'b6' id_b, 'c6' id_x, 'd6' id_d
UNION
SELECT 7 , 'a7' id_a, 'b7' id_b, 'c7' id_x, 'd7' id_d
UNION
SELECT 8 , 'a1' id_a, 'b8' id_b, 'c8' id_x, 'd8' id_d
UNION
SELECT 9 , 'a9' id_a, 'b8' id_b, 'c9' id_x, 'd9' id_d
Ответы (2 шт):
Если я правильно понял, то задачей подразумевается поиск одинаковых значений в столбцах.
Допустим, изначальная таблица имеет вид:
WITH testTable AS (
SELECT 1 row_id, 'a1' id_a, 'b1' id_b, 'c1' id_x, 'd1' id_d
UNION
SELECT 2 , 'a2' id_a, 'b2' id_b, 'c2' id_x, 'd9' id_d
UNION
SELECT 3 , 'a3' id_a, 'b3' id_b, 'c3' id_x, 'd3' id_d
UNION
SELECT 4 , 'a1' id_a, 'b4' id_b, 'c4' id_x, 'd4' id_d
UNION
SELECT 5 , 'a5' id_a, 'b5' id_b, 'c5' id_x, 'd5' id_d
UNION
SELECT 6 , 'a6' id_a, 'b6' id_b, 'c6' id_x, 'd6' id_d
UNION
SELECT 7 , 'a7' id_a, 'b7' id_b, 'c7' id_x, 'd7' id_d
UNION
SELECT 8 , 'a1' id_a, 'b8' id_b, 'c8' id_x, 'd8' id_d
UNION
SELECT 9 , 'a9' id_a, 'b8' id_b, 'c9' id_x, 'd9' id_d
),
Далее вращаем таблицу, чтобы можно было произвести поиск одинаковых значений:
pvt AS (
SELECT
pvt.col,
pvt.val,
pvt.row_id
FROM
testTable t
LEFT JOIN LATERAL (
SELECT
'id_a' AS col,
t.id_a AS val,
t.row_id
UNION ALL
SELECT
'id_b' AS col,
t.id_b AS val,
t.row_id
UNION ALL
SELECT
'id_x' AS col,
t.id_x AS val,
t.row_id
UNION ALL
SELECT
'id_d' AS col,
t.id_d AS val,
t.row_id
) pvt ON true
)
Ищем одинаковые значения по столбцам:
srh AS (
SELECT
t1.col,
t1.val,
t1.row_id
FROM
pvt t1
WHERE
EXISTS (
SELECT 1
FROM pvt t2
WHERE
t1.col = t2.col
AND t1.val = t2.val
AND t1.row_id != t2.row_id
)
ORDER BY
t1.col,
t1.val,
t1.row_id
)
Ну а какой вывод должен автор не указал... предполагаю так?
SELECT
s.col,
s.val,
ARRAY_AGG(s.row_id) AS row_ids
FROM
srh s
GROUP BY
s.col,
s.val
| col | val | row_ids |
|---|---|---|
| id_a | a1 | {1, 4, 8} |
| id_b | b8 | {8, 9} |
| id_d | d9 | {2, 9} |
Теперь условие стало понятнее.
Это похоже на задачу составления наибольших подсетей (связанных узлов) в сети.
Посмотрите вариант
-- тестовые данные
with recursive data as(
SELECT 1 row_id, 'a1' id_a, 'b1' id_b, 'c1' id_x, 'd1' id_d
UNION
SELECT 2 , 'a2' id_a, 'b2' id_b, 'c2' id_x, 'd9' id_d
UNION
SELECT 3 , 'a3' id_a, 'b3' id_b, 'c3' id_x, 'd5' id_d
UNION
SELECT 4 , 'a1' id_a, 'b4' id_b, 'c4' id_x, 'd4' id_d
UNION
SELECT 5 , 'a5' id_a, 'b5' id_b, 'c5' id_x, 'd5' id_d
UNION
SELECT 6 , 'a6' id_a, 'b6' id_b, 'c6' id_x, 'd6' id_d
UNION
SELECT 7 , 'a7' id_a, 'b7' id_b, 'c7' id_x, 'd7' id_d
UNION
SELECT 8 , 'a1' id_a, 'b8' id_b, 'c8' id_x, 'd8' id_d
UNION
SELECT 9 , 'a9' id_a, 'b8' id_b, 'c9' id_x, 'd9' id_d
)
-- пример запроса с рекурсией
,r as(
select 1 lvl,cast(row_id as varchar) path,row_id,id_a,id_b,id_x,id_d
from data
union all
select r.lvl+1
,path||','||cast(d.row_id as varchar)
,d.row_id,d.id_a,d.id_b,d.id_x,d.id_d
from r inner join data d
on (d.id_a=r.id_a or d.id_b=r.id_b or d.id_x=r.id_x or d.id_d=r.id_d)
where strpos(path,cast(d.row_id as varchar))=0
)
,t1 as(
select * ,unnest (string_to_array(path,',') ) gr
from r
)
,t2 as(
select row_id,min(gr) gr
from t1
group by row_id
)
select gr,STRING_AGG(cast(row_id as varchar),',' order by row_id) lst
from t2
group by gr
Результат
| gr | lst |
|---|---|
| 1 | 1,2,4,8,9 |
| 3 | 3,5 |
| 6 | 6 |
| 7 | 7 |
