关联单字段含多值的表:获取人员对应的组名集合
解决方案
你的问题核心是tbPerson表的groupid字段存储了逗号分隔的多个组ID,直接用等值关联无法匹配到所有对应组,需要先判断组ID是否存在于该字符串中,再将匹配到的组名聚合为一个字符串。
以下是不同数据库环境下的具体SQL实现:
MySQL
使用FIND_IN_SET判断组ID是否在逗号分隔列表中,再用GROUP_CONCAT聚合组名:
SELECT p.name, GROUP_CONCAT(g.group_name ORDER BY g.groupid SEPARATOR ', ') AS group_name FROM tbPerson p LEFT JOIN tbGroup g ON FIND_IN_SET(g.groupid, p.groupid) > 0 GROUP BY p.personid, p.name;
SQL Server(2017及以上版本)
使用STRING_AGG聚合,用CHARINDEX判断组ID是否存在:
SELECT p.name, STRING_AGG(g.group_name, ', ') WITHIN GROUP (ORDER BY g.groupid) AS group_name FROM tbPerson p LEFT JOIN tbGroup g ON CHARINDEX(',' + CAST(g.groupid AS VARCHAR) + ',', ',' + p.groupid + ',') > 0 GROUP BY p.personid, p.name;
如果是SQL Server 2016及更早版本,需要用STUFF结合FOR XML PATH实现聚合:
SELECT p.name, STUFF(( SELECT ', ' + g.group_name FROM tbGroup g WHERE CHARINDEX(',' + CAST(g.groupid AS VARCHAR) + ',', ',' + p.groupid + ',') > 0 ORDER BY g.groupid FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'), 1, 2, '') AS group_name FROM tbPerson p GROUP BY p.personid, p.name;
Oracle
使用REGEXP_LIKE匹配组ID,用LISTAGG聚合:
SELECT p.name, LISTAGG(g.group_name, ', ') WITHIN GROUP (ORDER BY g.groupid) AS group_name FROM tbPerson p LEFT JOIN tbGroup g ON REGEXP_LIKE(p.groupid, '(^|,)' || g.groupid || '(,|$)') GROUP BY p.personid, p.name;
说明
- 关联条件中使用
FIND_IN_SET/CHARINDEX/REGEXP_LIKE,是为了准确匹配单个组ID(避免出现类似组ID 12被误匹配为1的情况)。 - 聚合时添加
ORDER BY可以保证组名的顺序和原groupid中的ID顺序一致。
内容的提问来源于stack exchange,提问作者suncarl
相关产品推荐
相关产品推荐

