查询将行转换为列

时间:2013-08-07 00:41:46

标签: mysql sql database

在某些商业应用程序中,原始数据会进入,我会对其进行规范化和处理,并将其存储起来用于报告目的。

例如,原始数据:

Transaction (transaction ID, employee 1 ID, employee 2 ID, employee 3 ID)

归一化为

Transaction(transaction ID)

TransactionEmployee (transaction ID, employee ID)

在报告要求方面,员工必须排在一行 - 例如TransactionReport(transaction ID, some details, employee 1 ID, employee 2 ID, employee 3 ID)

我的解决方案是使用应用程序编程语言来循环TransactionEmployee,并构造INSERT语句以将报告数据放入另一个表 - 每个事务具有3个员工ID。

但是我觉得在SQL中做这件事会更舒服。

这可以通过SQL吗?

1 个答案:

答案 0 :(得分:0)

您可以这样做的一种方法是使用用户定义的变量为每个事务的每个员工创建一个行号,然后您可以通过应用带有CASE表达式的聚合函数将数据行转换为列:

select transactionid,
  max(case when row = 1 then employeeid end) employee1,
  max(case when row = 2 then employeeid end) employee2,
  max(case when row = 3 then employeeid end) employee3
from
(
  select t.transactionid,
    e.employeeid,
    @row:=case when @prev = t.transactionid then @row else 0 end +1 row,
    @prev:=t.transactionid
  from transaction t
  left join transactionemployee e
    on t.transactionid = e.transactionid
  cross join (select @row:=0, @prev = 0) c
  order by t.transactionid, e.employeeid
) d
group by transactionid
order by transactionid;

SQL Fiddle with Demo

如果您不想使用用户定义的变量,那么您可以使用类似于以下的子查询:

select transactionid,
  max(case when row = 1 then employeeid end) employee1,
  max(case when row = 2 then employeeid end) employee2,
  max(case when row = 3 then employeeid end) employee3
from
(
  select t.transactionid,
    e.employeeid,
    (select count(*)
     from transactionemployee te
     where e.transactionid = te.transactionid
       and te.employeeid <= e.employeeid) row
  from transaction t
  left join transactionemployee e
    on t.transactionid = e.transactionid
) d
group by transactionid;

请参阅SQL Fiddle with Demo