【问题标题】:Oracle LISTAGG() for multiple attributes?Oracle LISTAGG() 用于多个属性?
【发布时间】:2015-06-23 12:46:41
【问题描述】:

我想知道下面描述的问题是否有更好(即执行速度更快)的解决方案。

步骤 1)

create table t (k number, v1 number, v2 number);

insert into t values (1,1,1);
insert into t values (1,2,2);
insert into t values (1,2,3);
insert into t values (1,3,3);
insert into t values (1,4,3);  
insert into t values (2,7,8);
insert into t values (2,7,9);

第 2 步)

我想返回以下数据集

(k, v1_list, v2_list)
1, (1,2,3,4), (1,2,3)
2, (7), (8,9)

步骤 3)

我可以通过运行 listagg() 的多重组合来解决它,我想知道它是否可以通过另一种方式实现。 在此示例中,我处理 2 个属性,但实际上我必须为数百个列表运行类似的语句。如下所示的查询可能会变得很麻烦。我想知道它是否可以在一个查询中完成,可能使用 listagg() 多次?

with q1 as (
 select distinct k, listagg (v1, ', ') within group (order by k) over (partition by k) v1_list
 from   t
 group  by k, v1),
q2 as (
 select distinct k, listagg (v2, ', ') within group (order by k) over (partition by k) v2_list
 from   t
 group  by k, v2)
--
select distinct t.k, v1_list, v2_list from t       
--
join   q1 on q1.k = t.k
join   q2 on q2.k = t.k

感谢您的建议,

-- 卢卡斯

【问题讨论】:

    标签: string oracle aggregate-functions string-concatenation listagg


    【解决方案1】:

    你可以试试无证函数wm_concat

    select k, wm_concat(distinct(v1)), wm_concat(distinct(v2))
    from t
    group by k
    

    listagg

    select k, listagg(v1, ', ') within group (order by k), listagg(v2, ', ') within group (order by k)
    from (
        select distinct k, v1, null v2 from t  
        union all
        select distinct k, null v1, v2 from t
    )
    group by k
    

    【讨论】:

    • 逗号后面要加空格吗?
    • 但您还需要一个子查询来订购它,请参阅stackoverflow.com/questions/4970477/…。这对我来说看起来并不简单
    • 为你们的快速反应干杯。我很想检查 Dmitry 提出的关于我必须处理的大量数据的第二个解决方案,看看我是否达到了性能差异。如果我有任何结果,我会在这里发布结果,
    • 这是我的朋友提供的另一个解决方案。感谢菲利克斯,干杯伙伴!
    • 请提供:)
    【解决方案2】:
    select K, listagg(case when chgv1 = 1 then v1 else null end,',') within group (order by v1) as v1lst, --Only consider cases in listagg when rows have changed
              listagg(case when chgv2 = 1 then v2 else null end,',') within group (order by v2) as v2lst  --Only consider cases in listagg when rows have changed
    from (
     select k, v1, v2,
            row_number() over (partition by k,v1 order by v1 ) as chgv1, --Detect changes in v1. In this case it's 1.
            row_number() over (partition by k,v2 order by v1 ) as chgv2  --Detect changes in v1. In this case it's 1.
     from t)
    group by k;
    

    【讨论】:

      【解决方案3】:

      另一种方式:

      select t.k
      ,(select listagg(column_value,', ') within group (order by column_value)
        from table(v1)) v1 
      ,(select listagg(column_value,', ') within group (order by column_value)
        from table(v2)) v2 
      from (select k
                  ,cast(collect (distinct v1) as sys.odcinumberlist) v1
                  ,cast(collect (distinct v2) as sys.odcinumberlist) v2
            from T t
            group by k) t
      

      SQL Fiddle

      或不强制转换为 odcinumberlist:

       select t.k
          ,(select listagg(column_value,', ') within group (order by column_value)
            from table(v1)) v1 
          ,(select listagg(column_value,', ') within group (order by column_value)
            from table(v2)) v2 
          from (select k
                      ,collect (distinct v1) v1
                      ,collect (distinct v2) v2
                from T t
                group by k) t
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-29
        • 1970-01-01
        • 2021-06-03
        • 2020-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-10
        相关资源
        最近更新 更多