【问题标题】:Joining tables with different number of rows without duplicates连接具有不同行数且不重复的表
【发布时间】:2015-06-30 07:03:19
【问题描述】:

我有一个已经很复杂的 SQL 语句,它创建了一个用户表,这些用户拥有CONNECTAPPUSER 或两者的权限:

(SELECT  b.grantee AS "Username", A.granted_role AS "Connect", b.granted_role AS "APPUSER" FROM 
    (SELECT grantee, granted_role FROM dba_role_privs WHERE granted_role = 'CONNECT')  A 
    RIGHT OUTER JOIN 
    (SELECT grantee, granted_role FROM dba_role_privs WHERE granted_role = 'APPUSER') b 
    ON A.grantee=b.grantee) 
UNION 
(SELECT  A.grantee, A.granted_role, b.granted_role FROM 
    (SELECT grantee, granted_role FROM dba_role_privs WHERE granted_role = 'CONNECT')  A 
    LEFT OUTER JOIN 
    (SELECT grantee, granted_role FROM dba_role_privs WHERE granted_role = 'APPUSER') b 
    ON A.grantee=b.grantee)

这会产生类似:

Username        Connect        APPUSER
---------      ---------      ---------
Sue             CONNECT        APPUSER
Bob             (null)         APPUSER
Joe             CONNECT        (null)

我希望使用all_users 表来显示没有权限的用户。all_users 表显示数据库中的每个用户。

我尝试在我的 SQL 语句末尾添加几种类型的连接来实现这一点。我得到的最接近的是添加:

UNION
(SELECT username, NULL, NULL FROM all_users)

这将生成一个列表,其中每个用户显示两次,但显示的用户没有任何权利:

Username        Connect        APPUSER
---------      ---------      ---------
Amy             (null)         (null)
Sue             CONNECT        APPUSER
Sue             (null)         (null)
Bob             (null)         APPUSER
Bob             (null)         (null)
Joe             CONNECT        (null)
Joe             (null)         (null)

我尝试添加 where username = a.grantee,但这不适用于 Unions。如果我尝试用任何JOINs 替换UNION,比如添加:

FULL OUTER JOIN
SELECT username, NULL, NULL FROM ALL_USERS 
on username = a.grantee;

我得到错误:

“SQL 命令未正确结束”

【问题讨论】:

    标签: sql join oracle11g union


    【解决方案1】:

    您的查询似乎比必要的复杂得多。这是一种方法:

    select grantee,
           max(case when granted_role = 'CONNECT' then granted_role end) as "connect",
           max(case when granted_role = 'APPUSER' then granted_role end) as "appuser"
    from dba_role_privs
    group by grantee;
    

    如果有用户根本没有角色,那么您将需要all_users 表。

    编辑:

    只需使用left join

    select au.userName,
           max(case when granted_role = 'CONNECT' then granted_role end) as "connect",
           max(case when granted_role = 'APPUSER' then granted_role end) as "appuser"
    from all_users au join
         dba_role_privs rp
         on au.userName = rp.grantee
    group by au.userName;
    

    【讨论】:

    • 感谢您提供简化的方法。我确实有根本没有角色的用户。现在使用您提供的方法,看看我是否可以链接all_users 表。
    • 虽然简化的方法效果很好,但我仍然没有找到一种方法来使用all_users 表来显示没有角色的用户。
    【解决方案2】:

    我不太确定我是否理解第一个查询。当您可以使用 PIVOT 时,您似乎正在做一些非常复杂的事情。但是,如果它工作正常,那么您应该可以这样做:

    SELECT username 
    FROM ALL_USERS 
    WHERE username NOT IN (
    (SELECT DISTINCT b.grantee AS "Username", A.granted_role AS "Connect", b.granted_role AS "APPUSER" FROM 
            (SELECT grantee, granted_role FROM dba_role_privs WHERE granted_role = 'CONNECT')  A 
            RIGHT OUTER JOIN 
            (SELECT grantee, granted_role FROM dba_role_privs WHERE granted_role = 'APPUSER') b 
            ON A.grantee=b.grantee) 
        UNION 
        (SELECT  A.grantee, A.granted_role, b.granted_role FROM 
            (SELECT grantee, granted_role FROM dba_role_privs WHERE granted_role = 'CONNECT')  A 
            LEFT OUTER JOIN 
            (SELECT grantee, granted_role FROM dba_role_privs WHERE granted_role = 'APPUSER') b 
            ON A.grantee=b.grantee)
    )
    

    【讨论】:

    • 谢谢。我试过了,它给出了错误:“值太多”。
    • 嗯,抱歉,这通常适用于 SQL Server,但我刚刚意识到您使用的是 Oracle。尝试在其中添加 DISTINCT。查看我的最新编辑。如果这不起作用,也许使用“NOT EXISTS”而不是“NOT IN”?
    【解决方案3】:

    使用以下查询。让我知道这个是否奏效。您需要在 where 子句中添加 dp1.granted_role is null 和 dp2.granted_role is null。

    select     au.username,
               dp1.granted_role,
               dp2.granted_role
    
        from all_users au 
        left join dba_role_privs drp1 on drp1.grantee=au.username and drp1.granted_role='CONNECT'
        left join dba_role_privs drp2 on drp2.grantee=au.username and drp2.granted_role='APPUSER'
    

    【讨论】:

    • 您好,谢谢。您提供的查询给出了错误“表或视图不存在”。
    猜你喜欢
    • 2021-03-23
    • 2020-10-21
    • 2015-01-24
    • 2019-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多