【问题标题】:SQL LISTAGG for different types of valuesSQL LISTAGG 用于不同类型的值
【发布时间】:2016-07-20 03:51:03
【问题描述】:

我有下表

name   type            value 

a      mobile          123456  
a      home tel        456789  
a      Office addr     add1  
a      home addr       add2  
b      mobile          456456  
b      home tel        123123  
b      Office addr     add3  
b      home addr       add4  

我想做一个这样的SQL表

name    phone             address

a       123456; 456789    add1; add2  
b       456456; 123123    add3; add4  

我试过这个 SQL:

SELECT name, 
LISTAGG(t.CONTACT_INFO,';')
               WITHIN GROUP (ORDER BY type) AS phone where type in ('mobile', 'home tel'),
LISTAGG(t.CONTACT_INFO,';')
               WITHIN GROUP (ORDER BY type) AS address where type in ('Office addr', 'home addr')
FROM table t
  GROUP BY name

而且它不起作用。我知道是因为 WHERE 子句不是它需要的位置。但是我可以在哪里插入限制?如果我这样做

SELECT name, 
LISTAGG(t.CONTACT_INFO,';')
               WITHIN GROUP (ORDER BY type) AS phone,
LISTAGG(t.CONTACT_INFO,';')
               WITHIN GROUP (ORDER BY type) AS address
FROM table t
  GROUP BY name

看起来像

name    phone                         address

a       123456; 456789;add1; add2     123456; 456789;add1; add2  
b       456456; 123123;add3; add4     456456; 123123;add3; add4  

【问题讨论】:

    标签: sql oracle listagg


    【解决方案1】:

    可能是这样的,但我认为你的数据库设计很糟糕

    with a(name,type,value ) as (select 'a','mobile','123456' from dual union all
                                 select 'a','home tel','456789' from dual union all
                                 select 'a','Office addr', 'add1' from dual union all
                                 select 'a','home addr','add2' from dual union all
                                 select 'b','mobile','456456' from dual union all
                                 select 'b','home tel','123123' from dual union all
                                 select 'b','Office addr','add3' from dual union all
                                 select 'b','home addr', 'add4' from dual  )
    select a1.name,
           Listagg(a1.value, ';') Within Group (order by a1.type desc) phone,
           Listagg(a2.value, ';') Within Group (order by a2.type) address
      from a a1 inner join a a2 
            on decode(a1.type,'mobile','Office addr','home tel','home addr') = a2.type and a1.name = a2.name
    group by a1.name
    

    输出是:

    a   123456;456789   add1;add2
    b   456456;123123   add3;add4
    

    【讨论】:

      【解决方案2】:

      如果订单电话号码(手机、家庭)不重要 试试这个代码块:

      select t2.name
            ,listagg(t2.phone
                    ,';') within group(order by t2.phone) as phone
            ,listagg(t2.addresss
                    ,';') within group(order by t2.addresss) as addresss
        from (select t.name
                    ,case
                       when t.type in ('mobile'
                                      ,'home tel') then
                        listagg(t.value
                               ,';') within group(order by t.type)
                       else
                        null
                     end as phone
                    ,case
                       when t.type in ('Office addr'
                                      ,'home addr') then
                        listagg(t.value
                               ,';') within group(order by t.type)
                       else
                        null
                     end as addresss
                from table t
               group by t.name
                       ,t.type) t2
       group by t2.name
      

      给出这个结果:

       a   123456;456789   add1;add2
       b   123123;456456   add3;add4
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-14
        • 2012-07-15
        • 2021-03-09
        • 1970-01-01
        • 2023-04-07
        • 1970-01-01
        相关资源
        最近更新 更多