Выбрать все дочерние записи и сгруппировать по родителям - PullRequest
0 голосов
/ 31 октября 2018

У меня есть следующий блок данных -

+-----------+----------+
| parent_id | child_id |
+-----------+----------+
|         1 |       11 |
|         1 |       12 |
|         1 |       13 |
|         2 |       12 |
|         2 |       13 |
|         2 |       14 |
|         3 |       15 |
|         3 |       16 |
|         4 |       16 |
|         5 |       12 |
|         5 |       16 |
+-----------+----------+

Я хочу сделать оператор select, в котором я могу найти все child_id, принадлежащие родителям, и сгруппировать результаты, что-то вроде -

+-----------+----------+
| parent_id | child_id |
+-----------+----------+
|         1 | 12 & 13  |
|         2 |          |
+-----------+----------+ 
+-----------+----------+
| parent_id | child_id |
+-----------+----------+
|         1 |      12  |
|         2 |          |
|         5 |          |
+-----------+----------+
+-----------+----------+
| parent_id | child_id |
+-----------+----------+
|         3 |       16 |
|         4 |          |
|         5 |          |
+-----------+----------+

Итак, у родителей 1 и 2 у обоих есть дети 12 и 13 . Родители 1,2 и 5 все имеют 12 в детстве, и 3,4 и 5 все имеют 16 в детстве.

Ответы [ 2 ]

0 голосов
/ 31 октября 2018

Вы можете попробовать использовать cte для получения набора результатов, который содержит ваши ожидаемые значения parent_id и child_id, затем используйте FOR XML PATH, объедините их с &.

наконец, используйте row_number оконную функцию, создайте номер строки с помощью CASE WHEN, выполните функцию агрегирования, разрешите отображение только первой строки child_id.

;with cte as (
    SELECT t1.*
    FROM T t1 
    where 
       EXISTS (SELECT 1 FROM T tt WHERE t1.child_id = tt.child_id AND t1.parent_id <> tt.parent_id)
    AND 
       t1.parent_id in (1,2) --add you want to get parent_id id
), cte1 as (
     SELECT 
      distinct parent_id,
      STUFF((
         select  '&' + CAST(tt.child_id AS VARCHAR(MAX))  
         from cte tt 
         where t1.parent_id = tt.parent_id 
        FOR XML PATH(''),TYPE).value('.','VARCHAR(MAX)')
      ,1,1,'') AS child_id
     FROM cte t1
) 
SELECT parent_id,(case when rn = 1 then child_id else '' end) child_id
FROM (
   select *,row_number() over(order by parent_id) rn
   from cte1
) t1

Sqlfiddle

Результат

parent_id   child_id
1           12&13
2   
0 голосов
/ 31 октября 2018

Я думаю, что вы хотите:

SELECT t.*
FROM table t 
WHERE EXISTS (SELECT 1 FROM table t1 WHERE t1.child_id = t.child_id AND t1.parent_id <> t.parent_id);
...