CONTEXT

我正在使用SQL Server 2016.我try 按用户表的idusername分组,并从角色表中获取roleDesc,作为逗号分隔值.

  • #mapTable映射#userTable#roleTable表.
  • 一个用户可以拥有多个角色

所需结果:

id username roleDesc
1 user1 role1,role2
2 user1 role2

Issue

由于我使用的是SQL Server 2016,我无法使用STRING_AGGroleDesc分组为逗号分隔值.

My attempt

我试着用STUFF,但出错了.

IF(OBJECT_ID('Tempdb..#userTable') IS NOT NULL) 
    DROP TABLE #userTable

CREATE TABLE #userTable
(
    id int, 
    username nvarchar(200)
) 

INSERT INTO #userTable 
VALUES (1, 'user1'), 
       (2, 'user2') 
   
IF (OBJECT_ID('Tempdb..#roleTable') IS NOT NULL) 
    DROP TABLE #roleTable

CREATE TABLE #roleTable
(
    id int, 
    roleDesc nvarchar(200)
) 

INSERT INTO #roleTable 
VALUES (1, 'role1'), 
       (2, 'role2'), 
       (3, 'role3') 
  
IF(OBJECT_ID('Tempdb..#mapTable') IS NOT NULL) 
    DROP TABLE #mapTable

CREATE TABLE #mapTable
(
    id int, 
    map_userId int, 
    map_roleId int
) 

INSERT INTO #mapTable 
VALUES (1, 1, 1), 
       (2, 1, 2), 
       (3, 2, 2)
  
SELECT 
    U.id, 
    U.username,
    -- STRING_AGG(R.roleDesc,',')  roleDesc --> this works in SQL Server 2017
    STUFF ((SELECT 
                ',' + R.roleDesc 
            FROM 
                #roleTable T
            WHERE 
                T.id = R.id 
            FOR XML PATH('')), 1, 1, '') AS roleDesc 
FROM 
    #userTable U
JOIN 
    #mapTable MAP ON MAP.map_userId = U.id
JOIN 
    #roleTable R ON R.id = MAP.map_roleId
GROUP BY 
    U.id,  U.username

我提到的链接:

  1. https://stackoverflow.com/a/19348687/7067740
    • STUFF内的where子句ID最终用于外部查询GROUP BY.我的情况并非如此.
  2. https://stackoverflow.com/a/56964302/7067740
    • 这更接近我所需的解决方案,但是STUFF查询有一个更简单的WHERE子句.我无法将其翻译为我的 case .

我得到了这个错误:

列‘#roleTable.id’在 Select 列表中无效,因为它既未包含在聚合函数中,也未包含在GROUP BY子句中.

Question

另一种方法可能是什么?

推荐答案

外部查询不需要#roleTable#mapTable.将其移动到子查询

SELECT 
    U.id, 
    U.username,
    STUFF ((SELECT 
                ',' + R.roleDesc 
            FROM 
                #roleTable r
            JOIN
                #mapTable m 
            ON
                r.id = m.map_roleId
            WHERE 
                m.map_userId = U.id
            FOR XML PATH('')), 1, 1, '') AS roleDesc 
FROM 
    #userTable U
GROUP BY 
    U.id,  U.username

Sql相关问答推荐

在SQL Server中使用LEFT连接包含特定记录

判断Pyspark生成的SQL查询

用相同值更新行

如何通过比较不同表中相同ID S的值来筛选ID为S的列表?

SQL基于多个值 Select 单行

从原始表列中经过JSON字符串化的对象数组构建视图

从数据库中查找总和大于或等于查询中的数字的数字

按分类标准检索记录

在Postgres中合并相似的表

表函数的作用域和功能

VS代码无法识别SQL代码中带括号的字符串

通过UPDATE SELECT更新表时出现问题

将时间戳四舍五入到最近 10 分钟的查询

PostgreSQL - 从同一张表中获取值

使用其他表 SUM 的交换价格转换价格并获得 AVG

Snowflake 中的对象是如何比较的?

我需要遍历权重值表并确定每个权重是否有效

在 MySql 数据库中的两个日期之间搜索

在 SQL 的每行选项中 Select 最大值

连接表时避免重复