Sql 将名称之间的链接列表合并为一列

Sql 将名称之间的链接列表合并为一列,sql,sql-server,tsql,group-by,coalesce,Sql,Sql Server,Tsql,Group By,Coalesce,我目前有两个表用于存储实体之间的关系,如下所示: 实体\u表:包含实体的名称和类型(主实体或辅助实体) ENTITY_ID | ENTITY_NAME | ENTITY_TYPE ----------------------------------------- 1 | 'entity_1' | 'master' 2 | 'entity_2' | 'secondary' 3 | 'entity_3' | 'se

我目前有两个表用于存储实体之间的关系,如下所示:

实体\u表:包含实体的名称和类型(主实体或辅助实体)

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++代码< /LI>使用的
我要查找的内容:以以下格式返回所有实体及其链接实体的查询:

ENTITY_ID  |  ENTITY_TYPE  |  ENTITY_LINKS
------------------------------------------
1          |  'master'     |  2,3
2          |  'secondary'  |  1
3          |  'secondary'  |  1
...
我尝试过使用
COALESCE
JOIN
,但收效甚微,有什么办法可以做到这一点吗

链接列必须是“CSV格式”,所以它可以直接由C++代码使用,而不需要大量的循环,或者每个实体都有一个查询,这大大减慢了。


如果您知道如何将其放入视图中,视图也很好?

我认为这将为您提供所需内容。这将使用需要SQL Server 2017或更高版本的
STRING\u AGG
。如果您使用的是较旧版本的SQL Server,那么可以使用
STUFF
FOR XML PATH
(我认为Harry在上面提到了这一点)

你认为这会给你所需要的东西吗

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

我想这会给你你想要的。这将使用需要SQL Server 2017或更高版本的
STRING\u AGG
。如果您使用的是较旧版本的SQL Server,那么可以使用
STUFF
FOR XML PATH
(我认为Harry在上面提到了这一点)

你认为这会给你所需要的东西吗

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

您应该能够使用不同的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;

您应该能够使用不同的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;

查找XML的内容。。有很多例子there@Harry有什么例子吗?我不确定我是否理解您的意思XML与此有什么关系@HarryThis讲述了一个家庭的所有故事。而不是想如何去对数据进行反编译(并且可能在C++代码中SQL注入漏洞),你应该重构C++代码来处理SETUP。2017,介绍了@ GBeaveStRungAgg()。XML/STUFF方法是聚合字符串、查找XML内容的更好方法之一。。有很多例子there@Harry有什么例子吗?我不确定我是否理解您的意思XML与此有什么关系@HarryThis讲述了一个家庭的所有故事。而不是想如何去对数据进行反编译(并且可能在C++代码中SQL注入漏洞),你应该重构C++代码来处理SETUP。2017,介绍了@ GBeaveStRungAgg()。XML/STUFF方法是聚合字符串的更好方法之一,