我的桌子名称和分数如下所示:
+---------+---------+
| Name | Score |
+---------+---------+
| Joe | 1 |
+---------+---------+
| Joe | 4 |
+---------+---------+
| Joe | 2 |
+---------+---------+
| Joe | 5 |
+---------+---------+
| Steve | 4 |
+---------+---------+
| Steve | 2 |
+---------+---------+
| Steve | 1 |
+---------+---------+
输出要求是将行转置为列,因此结果表应如下所示:
+--------+---------+---------+---------+---------+
| Joe | 1 | 4 | 2 | 5 |
+--------+---------+---------+---------+---------+
| Steve | 4 | 2 | 1 | |
+--------+---------+---------+---------+---------+
问题是你看不到相同数量的行。对于Joe来说,有4行,而Steve有3行。
是否可以将行转换为列而不知道输出中应该有多少列?
答案 0 :(得分:0)
最简单的方法是省去单独的列,只使用group_concat()
。这会将得分放在一列中,并带有分隔符:
select name, group_concat(score) as scores
from table t
group by name;
SQL语句不能具有可变数量的输出列。您需要在select
中指定每个列。如果你有一个最大值,比如说5,你可以枚举值,然后转动:
select name,
max(case when rn = 1 then score end) as score_1,
max(case when rn = 2 then score end) as score_2,
max(case when rn = 3 then score end) as score_3,
max(case when rn = 4 then score end) as score_4,
max(case when rn = 5 then score end) as score_5
from (select t.*,
(@rn := if(@name = name, @rn + 1, if (@name := name, 1, 1))) as rn
from table t cross join
(select @rn := 0, @name := '') vars
order by name
) t
group by name;
如果你想要一个可变数量的列,你可以使用动态SQL(即准备好的语句)做类似的事情。
答案 1 :(得分:0)
我试过这样:检查一下
nam
是姓名
val
是得分
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'max(CASE WHEN val = ''',
val,
''' THEN val END) AS `',
(SELECT (
CASE nam
WHEN @curType
THEN @curRow := @curRow + 1
ELSE @curRow := 1 AND @curType := nam END
) + 1 AS rank
FROM tab1 p,
(SELECT @curRow := 0, @curType := '') r
where p.val=t.val and p.nam=t.nam
), '`'
)
) INTO @sql
FROM tab1 t;
SET @sql
= CONCAT('SELECT p.nam, ', @sql, '
from tab1 p
group by p.nam');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;