Microsoft SQL Server多对多关联表查询:合并客户ID为单行字段
解决SQL Server多对多关系下员工-客户合并显示问题
针对你的需求,要实现每个员工一行、客户ID逗号分隔的效果,核心是用分组聚合来合并同一员工的所有客户记录——SELECT DISTINCT只能去重完全相同的行,无法合并同一员工的多条客户数据,所以对你的场景无效。以下是两种适配不同SQL Server版本的解决方案:
方案1:SQL Server 2017及以上版本(推荐)
使用SQL Server内置的STRING_AGG函数,语法简洁高效:
-- 注意:请将Employee_Clients替换为你的实际关联表名称 SELECT e.Employoee_ID AS EmployeeID, CONCAT(e.Employee_FirstName, ' ', e.Employee_LastName) AS EmployeeName, -- 用ISNULL处理无客户的情况,显示空字符串而非NULL ISNULL(STRING_AGG(ec.ClientID, ', '), '') AS Clients FROM Employees e -- 左连接确保无客户的新员工也能被返回 LEFT JOIN Employee_Clients ec ON e.Employoee_ID = ec.EmployeeID -- 按员工唯一标识分组,保证一行一个员工 GROUP BY e.Employoee_ID, e.Employee_FirstName, e.Employee_LastName ORDER BY e.Employoee_ID;
关键说明:
LEFT JOIN:保留所有员工记录,即使没有对接客户,此时Clients字段会显示为空字符串(通过ISNULL处理)STRING_AGG:自动将分组内的ClientID用指定分隔符(这里是,)拼接成单个字符串GROUP BY:必须包含员工的唯一标识字段(ID和姓名),确保每个员工仅生成一行结果
方案2:SQL Server 2016及更早版本
如果你的SQL Server版本不支持STRING_AGG,可以用FOR XML PATH的方式实现字符串拼接:
-- 注意:请将Employee_Clients替换为你的实际关联表名称 SELECT e.Employoee_ID AS EmployeeID, CONCAT(e.Employee_FirstName, ' ', e.Employee_LastName) AS EmployeeName, -- 用STUFF去掉开头多余的", ",ISNULL处理无客户的情况 ISNULL(STUFF(( SELECT ', ' + CAST(ec.ClientID AS VARCHAR(10)) FROM Employee_Clients ec WHERE ec.EmployeeID = e.Employoee_ID FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'), 1, 2, ''), '') AS Clients FROM Employees e ORDER BY e.Employoee_ID;
关键说明:
- 子查询通过
FOR XML PATH('')将同一员工的所有ClientID拼接成类似, 22, 33的字符串 STUFF(..., 1, 2, ''):移除字符串开头的,,得到22, 33的格式- 同样通过
ISNULL确保无客户的员工显示空字符串而非NULL
内容的提问来源于stack exchange,提问作者r.shah
相关产品推荐
相关产品推荐

