如何使用CTE和联接优化查询

时间:2019-05-13 17:47:20

标签: sql sql-server sql-server-2012

我的查询有一个CTE,可以为每个用户排名。第二部分选择所有用户,并将每个角色转到一个新列。

CTE仍基于id加入,它永远需要运行查询。

任何建议都将不胜感激!

WITH UserRoles AS
(
    SELECT 
        ru.ID,
        ru.EmailAddress,
        r.RoleName,
        RANK() OVER (PARTITION BY IdentityUserID ORDER BY UserRoleName) AS RoleNumber
    FROM
        Users ru
    LEFT JOIN 
        User_Role r ON r.UserRoleID = ru.UserRoleID
    WHERE
        ru.UserID IS NOT NULL
)
SELECT
    l.[LastName],
    l.[FirstName],
    (SELECT TOP 1 RoleName 
     FROM UserRoles 
     WHERE UserRoles.ID = l.ID AND RoleNumber = 1) AS Role1,
    (SELECT TOP 1 RoleName 
     FROM UserRoles 
     WHERE UserRoles.ID = l.ID AND RoleNumber = 2) AS Role2,
    (SELECT TOP 1 RoleName 
     FROM UserRoles 
     WHERE UserRoles.ID = l.ID AND RoleNumber = 3) AS Role3,
    (SELECT TOP 1 RoleName 
     FROM UserRoles 
     WHERE UserRoles.ID = l.ID AND RoleNumber = 4) AS Role4,
    (SELECT TOP 1 RoleName 
     FROM UserRoles 
     WHERE UserRoles.ID = l.ID AND RoleNumber = 5) AS Role5
FROM 
    [dbo].[UserLogins] l
WHERE
    (SELECT TOP 1 UserRoleName 
     FROM UserRoles 
     WHERE UserRoles.ID = l.ID AND RoleNum = 1) IS NOT NULL

1 个答案:

答案 0 :(得分:1)

使用JOINGROUP BY而不是子查询。我想这就是你想要的:

SELECT l.LastName, l.FirstName,
       MAX(CASE WHEN seqnum = 1 THEN RoleName END) as Role1,
       MAX(CASE WHEN seqnum = 2 THEN RoleName END) as Role2,
       MAX(CASE WHEN seqnum = 3 THEN RoleName END) as Role3,
       MAX(CASE WHEN seqnum = 4 THEN RoleName END) as Role4,
       MAX(CASE WHEN seqnum = 5 THEN RoleName END) as Role5
FROM (SELECT l.LastName, l.FirstName, u.ID, u.EmailAddress, r.RoleName,
             row_number() over (partition by IdentityUserID order by UserRoleName) AS seqnum
      FROM Users u JOIN
           User_Role ur
           ON u.UserRoleID = ur.UserRoleID JOIN
           UserLogins ul
           ON ur.id = ul.id
      WHERE u.UserID is not null
     ) r
GROUP BY LastName, FirstName;