Объединить список ссылок между именами в один столбец - PullRequest
1 голос
/ 11 февраля 2020

В настоящее время у меня есть две таблицы, используемые для хранения отношений между сущностями, которые выглядят следующим образом:

Entity_Table : Содержит имена и типы ( master или вторичные ) сущностей

ENTITY_ID  |  ENTITY_NAME  |  ENTITY_TYPE
-----------------------------------------
1          |  'entity_1'   |  'master'
2          |  'entity_2'   |  'secondary'
3          |  'entity_3'   |  'secondary'
...

Таблица связей : содержит информацию об отношениях между сущностями

MASTER_ID  |  SECONDARY_ID
--------------------------
1          |  2
1          |  3
...

Дополнительная информация :

  • Существует около ~ 5000 сущностей, каждая может иметь несколько ссылок, некоторые не имеют ссылок
  • Эти таблицы используются внешним кодом C ++

Что я ищу : запрос, который вернул бы все сущности и связанные с ними сущности в этом формате:

ENTITY_ID  |  ENTITY_TYPE  |  ENTITY_LINKS
------------------------------------------
1          |  'master'     |  2,3
2          |  'secondary'  |  1
3          |  'secondary'  |  1
...

Я пытался использовать COALESCE и JOIN с небольшим успехом, любые идеи о том, как я мог бы достичь этого?

Столбец ссылок должен быть в "csv-подобном" формате, чтобы его можно было использовать непосредственно в коде c ++ без больших циклов for или с одним запросом на объект, который замедляется вещи значительно упали.

Vie Мы тоже хороши, если вы знаете, как это представить?

Ответы [ 2 ]

3 голосов
/ 11 февраля 2020

Я думаю, что это даст вам то, что вы после. При этом используется STRING_AGG, для чего требуется SQL Server 2017 или новее. Если вы используете старую версию SQL Server, вы можете использовать STUFF и FOR XML PATH (именно об этом, я думаю, Гарри говорил выше).

select e.entity_id, e.entity_type, string_agg(l.secondary_id, ',') as entity_links
from entity_table e
inner join links l on l.master_id = e.entity_id
group by e.entity_id, e.entity_type
union
select e.entity_id, e.entity_type, string_agg(l.master_id, ',') as entity_links
from entity_table e
inner join links l on l.secondary_id = e.entity_id
group by e.entity_id, e.entity_type

Думаю, это даст вам что вам нужно, используя STUFF.

select e.entity_id, e.entity_type, STUFF((SELECT distinct ',' + cast(l.secondary_id as varchar(20))
         from links l 
         where l.master_id = e.entity_id
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'') as entity_links
from entity_table e
inner join links l on l.master_id = e.entity_id
group by e.entity_id, e.entity_type
union
select e.entity_id, e.entity_type, STUFF((SELECT distinct ',' + cast(l.master_id as varchar(20))
         from links l 
         where l.secondary_id = e.entity_id
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'') as entity_links
from entity_table e
inner join links l on l.secondary_id = e.entity_id
group by e.entity_id, e.entity_type
2 голосов
/ 11 февраля 2020

Вы должны иметь возможность присоединиться к ссылкам дважды с другим предложением on, а затем объединиться, чтобы получить список связанных сущностей. затем используйте string_agg, чтобы поместить их все в один ряд, например:

SELECT e1.entity_id,
       e1.entity_type,
       string_agg(COALESCE(l1.secondary_id, l2.master_id), ',')
FROM entities e1
LEFT JOIN links l1 ON (e1.entity_id = l1.master_id AND e1.entity_type = 'master')
LEFT JOIN links l2 ON (e1.entity_id = l2.secondary_id AND e1.entity_type = 'secondary')
GROUP BY e1.entity_id;
...