如何在Mysql中取消透视表? [要求更好的方法]

时间:2018-12-29 07:18:17

标签: mysql sql

初始表格:

customer_id | order_A | order_B | order_C | order_D

       1 |       1 |       0 |       0 |       1 |
       2 |       0 |       1 |       0 |       1 |
       3 |       1 |       1 |       0 |       1 |
       4 |       0 |       0 |       0 |       1 |

必需的输出:

customer_id | order_type |

       1 | A          |
       1 | D          |
       2 | B          |
       2 | D          |
       3 | A          |
       3 | B          |
       3 | D          |
       4 | D          |

最初,我的问题被标记为重复,并被要求参考以下问题: MySQL pivot table

我引用了它,还借助http://archive.oreilly.com/oreillyschool/courses/dba1/提出了以下代码:

select customer_id,
 case when order_A=1 then 'A' end as order_type
 from tb1 having order_type is not null
Union all
 select customer_id,
 case when order_B=1 then 'B' end as order_type
 from tb1 having order_type is not null
Union all
 select customer_id,
 case when order_C=1 then 'C' end as order_type
 from tb1 having order_type is not null
Union all
 select customer_id,
 case when order_D=1 then 'D' end as order_type
 from tb1 having order_type is not null order by customer_id,order_type;

这段代码确实为我提供了所需的输出,但是我想知道是否有更好的方法/方法来解决这个问题。

此外,如果有人可以帮助建议我可以在访谈中练习此类问题的网站/书籍,那将是很大的帮助。

1 个答案:

答案 0 :(得分:1)

我会这样写:

select customerId, 'A' as order_type
from tb1
where order_A = 1
union all
select customerId, 'B' as order_type
from tb1
where order_B = 1
union all
select customerId, 'C' as order_type
from tb1
where order_C = 1
union all
select customerId, 'D' as order_type
from tb1
where order_D = 1;

条件逻辑全部在where中,而不是在case表达式和having子句之间分割。这也使用标准SQL,它将在任何数据库中工作(您对having的使用,而没有GROUP BY的使用是MySQL的扩展)。

如果您要从性能角度简化查询,则要消除这四个扫描。您可以这样做:

select tb1.customerId, o.order_type
from tb1 join
     (select 'A' as order_type union all
      select 'B' as order_type union all
      select 'C' as order_type union all
      select 'D' as order_type 
     ) o
     on (tb1.order_A = 1 and o.order_type = 'A') or
        (tb1.order_B = 1 and o.order_type = 'B') or
        (tb1.order_C = 1 and o.order_type = 'C') or
        (tb1.order_D = 1 and o.order_type = 'D') ;

这应该从tb1中读取一行,然后通过join操作进行四个比较。 union all方法读取该表四次。