在一行中返回SQL中的多对一组合

在一行中返回SQL中的多对一组合,sql,sql-server,performance,subquery,one-to-many,Sql,Sql Server,Performance,Subquery,One To Many,我有下列表格 User --------------------------- UserID, FirstName, LastName Role --------------------------- RoleID, UserID, RoleName 假设角色和用户之间存在多对一的关系,我可以在一个查询中返回一个用户以及他们可能在一行中的所有角色的最佳方式是什么 以前我总是在单独的查询中加载角色(或类似的数据),但问题是,如果您的数据增长过快,这种技术就会变得太慢。将您的数据放入包含更多列

我有下列表格

User
---------------------------
UserID, FirstName, LastName


Role
---------------------------
RoleID, UserID, RoleName
假设角色和用户之间存在多对一的关系,我可以在一个查询中返回一个用户以及他们可能在一行中的所有角色的最佳方式是什么


以前我总是在单独的查询中加载角色(或类似的数据),但问题是,如果您的数据增长过快,这种技术就会变得太慢。

将您的数据放入包含更多列的单行并不比返回包含更少列的多行更有效。创建和销毁连接可能是您所做的最昂贵的操作,因此您可能会考虑创建一个存储过程来包装两个查询,然后使用

访问结果。
WITH cte (userId, roleList, roleNameTemp, level)
as 
(
    SELECT  userId
            , CAST( '' AS VARCHAR(max) )
            , CAST( '' AS VARCHAR(200) )
            , 0 level
    FROM    Role
    GROUP BY UserId 
    UNION ALL
    SELECT  r.userId
            , roleList + 
                CASE WHEN level = 0 THEN '' ELSE ', ' END + RoleName 
            , CAST( RoleName AS VARCHAR(200))
            , level + 1
    FROM CTE c
    INNER JOIN Role r ON c.userId = r.userid
    WHERE   r.RoleName  > c.roleNameTemp 
)

SELECT      UserId
            ,FirstName
            ,LastName
            ,roleList 
FROM 
(
    SELECT      u.UserId
                ,u.FirstName
                ,u.LastName
                ,c.roleList 
                ,ROW_NUMBER() OVER (Partition by c.userid order by level desc) rowNumber
    FROM        cte c
    INNER JOIN  [User] u on c.userId = u.UserId
)   r
WHERE rownumber = 1


请参见使用光标或CTE获取单行数据