从同一个表中获取一对多的关系

时间:2014-02-21 19:06:55

标签: sql database oracle

我必须从同一个表中提取一对多的关系数据。 表的结构就像

____________________________________
| CUSTOMER_ID | SUBSCRIPTION_NAME |
-------------------------------------
|  1          |  ABC              |
|  1          |  TNT              |
|  1          |  AMC              |
|  2          |  ABC              |
|  2          |  USA              |
|  3          |  TNT              |
|  3          |  AMC              |
-------------------------------------

我想得到像

这样的输出
    | CUSTOMER_ID   |  SUBSCRIPTION_NAME |
    |  1            |  ABC,TNT,AMC       |
    |  2            |  ABC,USA           |
    |  3            |  TNT,AMC           |

2 个答案:

答案 0 :(得分:3)

SELECT customer_id,
   LISTAGG(subscription_name, '; ') WITHIN GROUP (ORDER BY subscription_name) AS subscription_name
FROM subscription
GROUP BY customer_id
ORDER BY customer_id;

Order by是可选的

答案 1 :(得分:0)

LISTAGG的几个替代品:

SQL> with t (CUSTOMER_ID, SUBSCRIPTION_NAME)
  2  as (
  3  select 1,  'ABC' from dual union all
  4  select 1,  'TNT' from dual union all
  5  select 1,  'AMC' from dual union all
  6  select 2,  'ABC' from dual union all
  7  select 2,  'USA' from dual union all
  8  select 3,  'TNT' from dual union all
  9  select 3,  'AMC' from dual
 10  )
 11  SELECT   CUSTOMER_ID,
 12           RTRIM(
 13              XMLAGG (XMLELEMENT(e, SUBSCRIPTION_NAME||',') ORDER BY SUBSCRIPTION_NAME).EXTRACT('//text()')
 14           ,',') AS x
 15      FROM t
 16  GROUP BY CUSTOMER_ID
 17  /

CUSTOMER_ID X                                                                   
----------- ----------------------------------------                            
          1 ABC,AMC,TNT                                                         
          2 ABC,USA                                                             
          3 AMC,TNT                                                             

SQL> with t (CUSTOMER_ID, SUBSCRIPTION_NAME)
  2  as (
  3  select 1,  'ABC' from dual union all
  4  select 1,  'TNT' from dual union all
  5  select 1,  'AMC' from dual union all
  6  select 2,  'ABC' from dual union all
  7  select 2,  'USA' from dual union all
  8  select 3,  'TNT' from dual union all
  9  select 3,  'AMC' from dual
 10  )
 11  select customer_id,
 12  max(substr(sys_connect_by_path( SUBSCRIPTION_NAME, ','),2)) x from
 13  (
 14  select customer_id, SUBSCRIPTION_NAME, row_number() over(partition by customer_id order by null) rn
 15  from t
 16  )
 17  start with rn=1
 18  connect by prior customer_id = customer_id and rn = prior rn+1
 19  group by customer_id
 20  /

CUSTOMER_ID X                                                                   
----------- ----------------------------------------                            
          1 ABC,TNT,AMC                                                         
          2 ABC,USA                                                             
          3 TNT,AMC