如何在SQL中返回多行聚合数据的多行

问题描述 投票:1回答:4

我有一个UserIds和角色名表。

例如:

UserId  Rolename
1       Admin
1       Editor
1       Other
2       Admin
3       Other

我想为每个包含UserId, IsAdmin, IsEditor的用户返回一行,后两列是布尔值,表示用户是否具有“Admin”角色或“Editor”角色。

从上面的例子我会得到以下输出:

UserId   IsAdmin  IsEditor
1        True     True
2        True     False
3        False    False

有什么想法吗?我一直在尝试使用group by,sub selection等集合函数的各种事情,但我只是没有得到它。

sql ibm-midrange
4个回答
1
投票

用户:

  UserId   UserName

    1        amir  
    2        john  
    3        sara  

用户角色:

  UserId   RoleName

    1        Admin  
    1        Editor  
    2        Editor  

查询:

   select UserId , 
     (select count(UserRoles.UserId) from userRoles where userRoles.UserId=users.UserId and RoleName='Admin' ) as IsAdmin ,
     (select count(userRoles.UserId) from userRoles where userRoles.UserId=users.UserId and RoleName='Editor' ) as IsEditor
    from users;

结果:

 UserId      IsAdmin   IsEditor
    1          1          1
    2          0          1
    3          0          0

2
投票

一种可能的方案:

SELECT
    UserId,
    CASE WHEN EXISTS (SELECT * FROM #UserRoles A WHERE A.UserId = UR.UserId AND A.Rolename = 'Admin') THEN 'True' ELSE 'False' END AS IsAdmin,
    CASE WHEN EXISTS (SELECT * FROM #UserRoles E WHERE E.UserId = UR.UserId AND E.Rolename = 'Editor') THEN 'True' ELSE 'False' END AS IsEditor
FROM
    UserRoles UR
GROUP BY
    UR.UserId

这个有效的语法是否取决于您使用的SQL类型 - Oracle?你没有指定。

另一种可能的方案

SELECT
    U.UserId,
    CASE WHEN A.UserId IS NOT NULL THEN 'True' ELSE 'False' END AS IsAdmin,
    CASE WHEN E.UserId IS NOT NULL THEN 'True' ELSE 'False' END AS IsEditor
FROM
    (
    SELECT DISTINCT
        UserId
    FROM
        UserRoles UR
    ) U
LEFT OUTER JOIN UserRoles A ON A.UserId = U.UserId AND A.Rolename = 'Admin'
LEFT OUTER JOIN UserRoles E ON E.UserId = U.UserId AND E.Rolename = 'Editor'

这些解决方案还假设您将永远不会为具有相同角色名称的相同用户ID分配多行。例如,表中具有Admin两次的用户ID 1。


1
投票
with data as (
select 1 userid, 'Admin' rolename from dual union all
select 1 userid,       'Editor' rolename from dual union all
select 1 userid,      'Other' rolename from dual union all
select 2 userid,      'Admin' rolename from dual union all
select 3 userid,      'Other' rolename from dual
)
select userid, 
max(case when rolename = 'Admin' then 'True' else 'False' end) isadmin,
max(case when rolename = 'Editor' then 'True' else 'False'  end) iseditor ,
max(case when rolename = 'Other' then 'True' else 'False'  end) isother
from data 
group by userid

OUTPUT:

USERID     ISADMIN ISEDITOR ISOTHER
---------- ------- -------- -------
     1     True    True     True    
     2     True    False    False   
     3     False   False    True    

0
投票

有几种方法可以做到这一点。假设您的表名为USERROLE,这适用于DB2 for i 6.1上的示例数据:

WITH adminrole(UserId, RoleName) AS (
  SELECT UserId, RoleName FROM userrole WHERE RoleName = 'Admin'),

editorrole(UserId, RoleName) AS (
  SELECT UserId, RoleName FROM userrole WHERE RoleName = 'Editor'),

groupid(UserId) AS (
  SELECT UserId FROM userrole GROUP BY UserId)

SELECT groupid.UserId,
       CASE WHEN adminrole.RoleName = 'Admin'
            THEN 'True' ELSE 'False' END AS IsAdmin,
       CASE WHEN editorrole.RoleName = 'Editor'
            THEN 'True' ELSE 'False' END AS IsEditor
FROM groupid LEFT OUTER JOIN adminrole
                  ON groupid.UserId = adminrole.UserId
             LEFT OUTER JOIN editorrole
                  ON groupid.UserId = editorrole.UserId

STRSQL的输出如下:

....+....1....+....2....+....3...
       USERID   ISADMIN  ISEDITOR
            1    True     True   
            2    True     False  
            3    False    False  
********  End of data  ********  

USERID列在我的测试数据中定义为INTEGER。

应该可以在V5R3到现在的任何地方工作。将表名从USERROLE更改为您的表名。

可以进行各种更改,但需要更多信息才能知道什么才是真正的好结构。

© www.soinside.com 2019 - 2024. All rights reserved.