sql如何垂直转换数据

时间:2013-04-09 16:11:36

标签: sql oracle plsql

我有3个数据经销商,payment_type和dealer_payment_type

  Dealer : dealer_id , dealer_name, dealer_address
              1      | test      |  123 test lane
              2      | abc       |  abc lane  
              3      | def       |  def lane


 Payment_type : paymenttype_id , paytype 
                   1           | CHECK
                   2           | WIRE
                   3           | CREDIT

  Dealer_Payment_type : DPT_id , dealer_id , payment_type_id
                         1     |   1       | 1
                         2     |   1       | 2
                         3     |   1       | 3
                         4     |   2       | 2
                         5     |   2       | 3
                         6     |   3       | 1
                         7     |   3       | 2

我必须写一个查询来获取每个经销商的付款类型信息,查询需要返回这样的数据:

         dealer_id , dealer_name , paytype           
           1       |  test       | check,wire,credit
           2       |  abc        | wire,credit
           3       |  def        | check,wire

                    OR

      dealer_id , dealer_name  , check , wire , credit
       1        | test         | true  | true  | true 
       2        | abc          | false | true  | true 
       3        | def          | true  | false | true

1 个答案:

答案 0 :(得分:2)

您没有指定您正在使用的Oracle版本。

如果您使用的是Oracle 11g,则可以使用以下内容。

要将值添加到单个列中,您可以使用LISTAGG

select d.dealer_id,
  d.dealer_name,
  listagg(p.paytype, ',') within group (order by d.dealer_id) as paytype
from dealer d
left join Dealer_Payment_type dp
  on d.dealer_id = dp.dealer_id
left join payment_type p
  on dp.payment_type_id = p.paymenttype_id
group by d.dealer_id, d.dealer_name;

请参阅SQL Fiddle with demo

要获取单独列中的值,可以使用PIVOT:

select dealer_id, dealer_name,
  coalesce("Check", 'false') "Check",
  coalesce("Wire", 'false') "Wire",
  coalesce("Credit", 'false') "Credit"
from
(
  select d.dealer_id,
    d.dealer_name,
    p.paytype, 
    'true' flag
  from dealer d
  left join Dealer_Payment_type dp
    on d.dealer_id = dp.dealer_id
  left join payment_type p
    on dp.payment_type_id = p.paymenttype_id
)
pivot
(
  max(flag)
  for paytype in ('CHECK' as "Check", 'WIRE' as "Wire", 'CREDIT' as "Credit")
)

请参阅SQL Fiddle with Demo

如果您不使用Oracle 11g,则可以使用wm_concat()将值连接成一行:

select d.dealer_id,
  d.dealer_name,
  wm_concat(p.paytype) as paytype
from dealer d
left join Dealer_Payment_type dp
  on d.dealer_id = dp.dealer_id
left join payment_type p
  on dp.payment_type_id = p.paymenttype_id
group by d.dealer_id, d.dealer_name;

要创建单独的列,您可以使用带有CASE的聚合函数:

select dealer_id, dealer_name,
  max(case when paytype = 'CHECK' then flag else 'false' end) "Check",
  max(case when paytype = 'WIRE' then flag else 'false' end) "Wire",
  max(case when paytype = 'CREDIT' then flag else 'false' end) "Credit"
from
(
  select d.dealer_id,
    d.dealer_name,
    p.paytype, 
    'true' flag
  from dealer d
  left join Dealer_Payment_type dp
    on d.dealer_id = dp.dealer_id
  left join payment_type p
    on dp.payment_type_id = p.paymenttype_id
)
group by dealer_id, dealer_name;

请参阅SQL Fiddle with Demo