我在 HackerRank 上也遇到过这个问题。虽然我认为group_concat 的答案非常好,并且通常用于早期版本的 MySql 的此类关键情况,但我发现concat 和group_concat 可能难以阅读和理解。
如果您的 MySql 版本支持 窗口函数,那么您可以使用临时表来解决这个问题,因为 MySql 不支持外连接。您需要为每个数据透视列创建一个单独的临时表,以避免 Window function is not allowed in window specification 错误:
use test;
drop table if exists occupations;
create table if not exists occupations (
name varchar(50)
,occupation varchar(50)
);
insert into occupations (name, occupation) select 'Samantha', 'Doctor'
union all select 'Julia', 'Actor'
union all select 'Maria', 'Actor'
union all select 'Meera', 'Singer'
union all select 'Ashley', 'Professor'
union all select 'Kelly', 'Professor'
union all select 'Christeen', 'Professor'
;
-- the way to approach this in mysql is to create a temp table with ordinals.
-- then upsert with four queries using row_number()
-- nb full join not supported. let's try temp table
drop table if exists doctors;
create temporary table doctors
(
name varchar(50)
,occupation varchar(50)
,ordinal int
);
insert into doctors
select
name
,occupation
,row_number() over (partition by occupation order by name) as ordinal
from occupations
where occupation = 'Doctor'
;
drop table if exists actors;
create temporary table actors
(
name varchar(50)
,occupation varchar(50)
,ordinal int
);
insert into actors
select
name
,occupation
,row_number() over (partition by occupation order by name) as ordinal
from occupations
where occupation = 'Actor'
;
drop table if exists professors;
create temporary table professors
(
name varchar(50)
,occupation varchar(50)
,ordinal int
);
insert into professors
select
name
,occupation
,row_number() over (partition by occupation order by name) as ordinal
from occupations
where occupation = 'Professor'
;
drop table if exists singers;
create temporary table singers
(
name varchar(50)
,occupation varchar(50)
,ordinal int
);
insert into singers
select
name
,occupation
,row_number() over (partition by occupation order by name) as ordinal
from occupations
where occupation = 'Singer'
;
-- upsert: update if not exists
drop table if exists results;
create temporary table results
(
singer varchar(50)
,actor varchar(50)
,doctor varchar(50)
,professor varchar(50)
,ordinal int primary key
);
insert into results (singer, ordinal)
select name, ordinal from singers
on duplicate key update singer = name
;
insert into results (actor, ordinal)
select name, ordinal from actors
on duplicate key update actor = name
;
insert into results (doctor, ordinal)
select name, ordinal from doctors
on duplicate key update doctor = name
;
insert into results (professor, ordinal)
select name, ordinal from professors
on duplicate key update professor = name
;
select singer, actor, doctor, professor from results;
附言。我不得不不同意早期的 cmets:这是一个支点。我们将行投影到列中,行是职业和序数的投影。