Возврат многозначного композита в SQL в одну строку - PullRequest
0 голосов
/ 18 августа 2011

У меня есть следующие таблицы

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


Role
---------------------------
RoleID, UserID, RoleName

Если предположить, что между ролью и пользователем существует отношение «один к одному», как лучше всего вернуть в одном запросе пользователя вместе со всеми ролями, в которых он может быть,в одной строке?

Ранее я всегда загружал роли (или аналогичные данные) в отдельном запросе, но проблема в том, что если ваши данные растут, эта техника становится слишком медленной.

Ответы [ 2 ]

1 голос
/ 18 августа 2011

Это должно дать вам одну строку на пользователя в следующем формате

Single user, multiple roles

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
1 голос
/ 18 августа 2011

Получение данных в одну строку с большим количеством столбцов по своей сути не является более эффективным, чем возврат нескольких строк с меньшим количеством столбцов.Создание и удаление соединения, вероятно, является самой дорогой из выполняемых вами операций, поэтому вы можете рассмотреть вопрос о создании хранимой процедуры, которая упаковывает оба запроса, а затем получить доступ к результатам, используя NextResult

...