将名称之间的链接列表合并到一个列中
Coalesce list of links between names into a single column
我目前有两个 table 用于存储实体之间的关系,如下所示:
Entity_Table:包含名称和类型(master or secondary)实体数
ENTITY_ID | ENTITY_NAME | ENTITY_TYPE
-----------------------------------------
1 | 'entity_1' | 'master'
2 | 'entity_2' | 'secondary'
3 | 'entity_3' | 'secondary'
...
链接table:包含实体之间的关系信息
MASTER_ID | SECONDARY_ID
--------------------------
1 | 2
1 | 3
...
附加信息:
- 大约有 ~5000 个实体,每个实体可以有多个链接,有些没有链接
- 这些table被外部c++代码使用
我在找什么:一个查询 return 所有实体及其链接实体的格式如下:
ENTITY_ID | ENTITY_TYPE | ENTITY_LINKS
------------------------------------------
1 | 'master' | 2,3
2 | 'secondary' | 1
3 | 'secondary' | 1
...
我已经尝试使用 COALESCE
和 JOIN
但收效甚微,关于如何实现这一点有什么想法吗?
链接列必须采用 "csv-like" 格式,以便后面的 c++ 代码可以直接使用它,而无需大量的 for 循环或每个实体都有一个查询,这会大大降低速度。
如果您知道如何将其放入视图中,视图也很不错?
我想这会给你你想要的。这使用 STRING_AGG
需要 SQL Server 2017 或更新版本。如果您使用的是旧版本的 SQL 服务器,您可以使用 STUFF
和 FOR XML PATH
(我认为 Harry 在上面所说的)。
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
您应该能够使用不同的 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;
我目前有两个 table 用于存储实体之间的关系,如下所示:
Entity_Table:包含名称和类型(master or secondary)实体数
ENTITY_ID | ENTITY_NAME | ENTITY_TYPE
-----------------------------------------
1 | 'entity_1' | 'master'
2 | 'entity_2' | 'secondary'
3 | 'entity_3' | 'secondary'
...
链接table:包含实体之间的关系信息
MASTER_ID | SECONDARY_ID
--------------------------
1 | 2
1 | 3
...
附加信息:
- 大约有 ~5000 个实体,每个实体可以有多个链接,有些没有链接
- 这些table被外部c++代码使用
我在找什么:一个查询 return 所有实体及其链接实体的格式如下:
ENTITY_ID | ENTITY_TYPE | ENTITY_LINKS
------------------------------------------
1 | 'master' | 2,3
2 | 'secondary' | 1
3 | 'secondary' | 1
...
我已经尝试使用 COALESCE
和 JOIN
但收效甚微,关于如何实现这一点有什么想法吗?
链接列必须采用 "csv-like" 格式,以便后面的 c++ 代码可以直接使用它,而无需大量的 for 循环或每个实体都有一个查询,这会大大降低速度。
如果您知道如何将其放入视图中,视图也很不错?
我想这会给你你想要的。这使用 STRING_AGG
需要 SQL Server 2017 或更新版本。如果您使用的是旧版本的 SQL 服务器,您可以使用 STUFF
和 FOR XML PATH
(我认为 Harry 在上面所说的)。
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
您应该能够使用不同的 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;