mysql pivot table with string values

2019-06-06 18:04发布

I have a table with just two columns like this

mysql> select * from stuff_table;
+------+-------+
| name | stuff |
+------+-------+
| John | shoes |
| Jim  | bag   |
| Ely  | book  |
| Tom  | bag   |
| Will | shoes |
| Pitt | book  |
| Dean | bag   |
| Luke | bag   |
+------+-------+

and I tried with many solutions I found like

select distinct
max(case when stuff='shoes' then name else name is null) end as shoes,
max(case when stuff='bag' then name else name is null end) as bag,
max(case when stuff='book' then name else name is null end) as book
from stuff_table;

but I just got this

+-------+------+------+
| shoes | bag  | book |
+-------+------+------+
| Will  | Tom  | Pitt |
+-------+------+------+

Instead, I want to get this

+-------+------+------+
| shoes | bag  | book |
+-------+------+------+
| John  | Jim  | Ely  |
| Will  | Tom  | Pitt |
| NULL  | Dean | NULL |
| NULL  | Luke | NULL |
+-------+------+------+

I have tried with sum(case...) or if(case..) or group by too but it doesn't work. Is there any mysql query to get such that table? Kindly help. Thank you.

2条回答
叛逆
2楼-- · 2019-06-06 18:25

You dont need to use else and You have a end outside of max function :

select distinct
max(case when stuff='shoes' then name end ) as shoes,
max(case when stuff='bag' then name  end) as bag,
max(case when stuff='book' then name  end) as book
from stuff_table;
查看更多
来,给爷笑一个
3楼-- · 2019-06-06 18:31

Depending on the version of mysql you are using, here's one approach establishing a row_number per group, then using conditional aggregation grouped by that row number:

select 
    rn, 
    max(case when stuff = 'bag' then name end) 'bag',
    max(case when stuff = 'book' then name end) 'book',
    max(case when stuff = 'shoes' then name end) 'shoes' 
from (
  select *, row_number() over (partition by stuff order by name) rn
  from stuff_table
) t
group by rn

Since you are using an older version of mysql, you'll need to use user-defined variables to establish the row number. The rest then works the same. Here's an example:

select 
    rn, 
    max(case when stuff = 'bag' then name end) 'bag',
    max(case when stuff = 'book' then name end) 'book',
    max(case when stuff = 'shoes' then name end) 'shoes' 
from (
  select *, 
  ( case stuff 
         when @curStuff
         then @curRow := @curRow + 1 
         else @curRow := 1 and @curStuff := stuff 
   end
  ) + 1 AS rn
  from stuff_table, (select @curRow := 0, @curStuff := '') r
  order by stuff
) t
group by rn
查看更多
登录 后发表回答