初始表格:
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;
这段代码确实为我提供了所需的输出,但是我想知道是否有更好的方法/方法来解决这个问题。
此外,如果有人可以帮助建议我可以在访谈中练习此类问题的网站/书籍,那将是很大的帮助。
答案 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
方法读取该表四次。