【问题标题】:Oracle Using ListAgg, distinct values, across multiple columnsOracle 使用 ListAgg,不同的值,跨多个列
【发布时间】:2016-07-01 15:56:47
【问题描述】:

对于 Oracle 12c... 我有一个销售给公司的行项目表。此表具有向该公司销售的代表的 3 级层次结构。其中一列是公司名称。我需要帮助编写 SQL 来生成一个逗号分隔的、唯一的所有人姓名列表,跨越所有三列,跨越卖给这家公司的所有行。举个例子……

CompanyName  Rep      Manager     GVP
-----------  -------  --------   --------
Sears        Bob      Tim        Frank
Sears        Jack     Tim        Frank
Ace          Scott    Chris      Bill

当我查看 Sears 时,SQL 应该返回“Bob, Jack, Tim, Frank”。名称的顺序无关紧要,只是它们是唯一的,并且它们包括来自所有 3 个字段的名称。我会假设这是一种 ListAgg 查询,但可能是错误的......

【问题讨论】:

    标签: sql oracle listagg


    【解决方案1】:

    使用UNPIVOT 运算符(它只会进行一次表扫描,而使用UNION 通常会为联合语句中的每个SELECT 进行一次表扫描):

    Oracle 设置

    CREATE TABLE table_name ( CompanyName, Rep, Manager, GVP ) AS
    SELECT 'Sears', 'Bob',   'Tim',   'Frank' FROM DUAL UNION ALL
    SELECT 'Sears', 'Jack',  'Tim',   'Frank' FROM DUAL UNION ALL
    SELECT 'Ace',   'Scott', 'Chris', 'Bill'  FROM DUAL;
    

    查询

    SELECT CompanyName,
           LISTAGG( Name, ',' ) WITHIN GROUP ( ORDER BY Name ) AS Names
    FROM   (
      SELECT DISTINCT
             CompanyName,
             Name
      FROM   table_name
      UNPIVOT( name FOR typ IN ( Rep, Manager, GVP ) )
    )
    GROUP BY CompanyName;
    

    输出

    COMPANYNAME NAMES
    ----------- ------------------
    Ace         Bill,Chris,Scott
    Sears       Bob,Frank,Jack,Tim
    

    【讨论】:

    • 我选择这种方法作为答案是因为它只需要读取一次数据。作为奖励,我必须承认,我从未见过以这种方式使用 CTAS(创建表作为选择)。我喜欢它。
    【解决方案2】:

    您需要取消透视数据(以删除重复项),然后重新聚合它:

    select companyname, listagg(person, ',') within group (order by person) as persons
    from ((select companyname, repfrom as person t) union
          (select companyname, manager from t) union
          (select companyname, gvp from t)
         ) t
    group by companyname;
    

    【讨论】:

      【解决方案3】:

      这个 SQL 应该可以解决问题:

      select listagg(p, ', ') within group (order by p) from (
        select rep p
        from   your_table
        union
        select manager p
        from   your_table
        union
        select gvp p
        from   your_table);
      

      【讨论】:

      • 这不会按CompanyName划分名称。
      • 是的,没错,但它显示了首先使用UNION 删除重复项,然后使用LISTAGG 进行聚合的总体思路。
      猜你喜欢
      • 1970-01-01
      • 2012-07-15
      • 2021-03-09
      • 2021-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-27
      相关资源
      最近更新 更多