我有这张桌子:
Id name degree
1 Ahmad BS
2 John MA
3 Abed MA
4 Sami DR
5 Mona BS
6 Sara BS
我想根据程度拆分名称,这样程度就是标题,列中的任何空值都会用NULL填充
并且列中的名称将按Apathetically排序。
结果应该是:
BS MA DR
Ahmad Abed Sami
Mona John NULL
Sara NULL NULL
我尝试了什么:
SELECT
GROUP_CONCAT(if(degree = 'BS', name, NULL)) AS 'BS',
GROUP_CONCAT(if(degree = 'MA', name, NULL)) AS 'MA',
GROUP_CONCAT(if(degree = 'DR', name, NULL)) AS 'DR'
FROM persons
GROUP BY name;
但似乎不正确。
答案 0 :(得分:1)
SET @rn1 := 0, @rn2 := 0, @rn3 := 0;
SELECT MAX(bs) AS `BS`,
MAX(ms) AS `MS`,
MAX(dr) AS `DR`
FROM (
SELECT CASE WHEN degree = 'BS' THEN @rn1 := @rn1 + 1
WHEN degree = 'MA' THEN @rn2 := @rn2 + 1
WHEN degree = 'DR' THEN @rn3 := @rn3 + 1
END AS `Row Number`,
IF(degree = 'BS', name, NULL) AS `bs`,
IF(degree = 'MA', name, NULL) AS `ma`,
IF(degree = 'DR', name, NULL) AS `dr`
FROM persons
ORDER BY name
) AS temp
GROUP BY `Row Number`
由于我们希望将原始表中不同行的值放在pivoted表的同一行中,我们可以为每列设置一个单独的行号计数器(在本例中,三个计数器用于三种类型的度数),所以我们可以根据它们的行号将它们全部放在同一行。
在临时表中,我们列出了单独行中的所有值,并使用NULL填充行中的其他单元格。我们还根据度数类型递增计数器。回到外部查询,我们可以使用MAX()
(或MIN()
)函数来显示该列中该特定行号的唯一非NULL值。
我希望这有助于某人。我正在寻找一个几乎完全相同的问题的答案,当我终于找到它时,我决定在StackExchange上注册,所以我可以回答这个问题。 SE社区为我提供了很多次有用的解决方案,这似乎是公平的:)
答案 1 :(得分:0)
select subBS.name as BS,
subMA.name as MA,
subDR.name as DR
from (select @rn1:=0, @rn2:=0, @rn3:=0) rn,
(select name, @rn1:=@rn1+1 as row
from t
where degree='BS') subBS
full outer join
(select name, @rn1:=@rn1+1 as row
from t
where degree='MA') subMA on subBS.row=subMA.row
full outer join
(select name, @rn1:=@rn1+1 as row
from t
where degree='DR') subDR on subBS.row=subDR.row
基于人工子查询的另一次尝试,其中行数大于每个子查询
我们将子查询定义为基于表的行数而没有限制,然后跳过空记录
select subBS.name as BS,
subMA.name as MA,
subDR.name as DR
from (select @rn:=0, @rn1:=0, @rn2:=0, @rn3:=0) rn,
(select @rn:=@rn+1 as row
from t) as main
left outer join on main.row=subMA.row
(select name, @rn1:=@rn1+1 as row
from t
where degree='BS'
order by name) subBS
left outer join
(select name, @rn2:=@rn2+1 as row
from t
where degree='MA'
order by name) subMA on main.row=subMA.row
left outer join
(select name, @rn3:=@rn3+1 as row
from t
where degree='DR'
order by name) subDR on main.row=subDR.row
where subBS.name is not null
or subMA.name is not null
or subDR.name is not null