Sql 如何从多个LISTAGG';Oracle中的非结构化列

Sql 如何从多个LISTAGG';Oracle中的非结构化列,sql,oracle11g,oracle-sqldeveloper,Sql,Oracle11g,Oracle Sqldeveloper,在下面的脚本中,我缺少什么逻辑来消除Listag函数中的重复值 下面是sys.privs表: SQL> desc sys.privs Name Null? Type ----------------------------------------- -------- ---------------------------- GRANTEE

在下面的脚本中,我缺少什么逻辑来消除Listag函数中的重复值

下面是sys.privs表:

SQL> desc sys.privs
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 GRANTEE                                            VARCHAR2(30 CHAR)
 GRANTED_ROLE                              NOT NULL VARCHAR2(30)
 PRIVILEGE                                 NOT NULL VARCHAR2(40)
 OWNER                                     NOT NULL VARCHAR2(30)
 TABLE_NAME                                NOT NULL VARCHAR2(30)
下面是脚本

SELECT grantee,
     LISTAGG(granted_role, '-') WITHIN GROUP (ORDER BY granted_role) AS granted_role,
     LISTAGG(privilege, '-') WITHIN GROUP (ORDER BY privilege) AS privs,
     owner,
     table_name
FROM (
     SELECT UNIQUE
            grantee,
            granted_role,
            privilege,
            owner,
            table_name
       FROM sys.privs
     )
GROUP BY grantee, owner, table_name;

您可以利用
listag()
忽略
NULL
值这一事实来实现这一点。因此,使用
row_number()
枚举重复项,然后只拉入第一个值:

SELECT grantee,
       LISTAGG(CASE WHEN seqnum_granted_role = 1 THEN granted_role END, '-')
           WITHIN GROUP (ORDER BY granted_role) AS granted_role,
       LISTAGG(CASE WHEN seqnum_privilege = 1 THEN privilege END, '-')
           WITHIN GROUP (ORDER BY privilege) AS privs,
       owner,
       table_name
FROM (SELECT grantee, granted_role, privilege,
             owner, table_name,
             ROW_NUMBER() OVER (PARTITION BY grantee, owner, table_name, granted_role
                                ORDER BY grantee
                               ) as seqnum_granted_role,
             ROW_NUMBER() OVER (PARTITION BY grantee, owner, table_name, privilege
                                ORDER BY grantee
                               ) as seqnum_privilege
       FROM sys.privs
     ) p
GROUP BY grantee, owner, table_name;