leetcode618. 学生地理信息报告(困难)

题目
一所美国大学有来自亚洲、欧洲和美洲的学生,他们的地理信息存放在如下 student 表中。

name continent
Jack America
Pascal Europe
Xi Asia
Jane America

写一个查询语句实现对大洲(continent)列的 透视表 操作,使得每个学生按照姓名的字母顺序依次排列在对应的大洲下面。输出的标题应依次为美洲(America)、亚洲(Asia)和欧洲(Europe)。数据保证来自美洲的学生不少于来自亚洲或者欧洲的学生。

对于样例输入,它的对应输出是:

America Asia Europe
Jack Xi Pascal
Jane

进阶:如果不能确定哪个大洲的学生数最多,你可以写出一个查询去生成上述学生报告吗?

生成数据

CREATE TABLE student2 (NAME VARCHAR(25),continent VARCHAR(25));
 
INSERT INTO student2 VALUES('Jack','America');
INSERT INTO student2 VALUES('Pascal','Europe');
INSERT INTO student2 VALUES('Xi','Asia');
INSERT INTO student2 VALUES('Jane','America');

审题
这特喵不就是长数据转宽数据么 py、R一下就可以实现的 这里也可能就是了解长转宽的底层逻辑吧。。

解答

重点是两步
第一,确定每个属性中各个数据所在的数据行。 其实是求每个数据的排名。
第二,确定每个数据行都有哪些数据。按照排名放置数据。

定义变量对每个周进行排名 这个之前做过比较多次了 直接写

SELECT S.`continent`, S.`name`, 
IF(S.`continent`=@pre_con, @rank:= @rank+1, @rank:=1) AS rank, 
@pre_con:= S.`continent` AS pre_con
FROM student2 AS S, (SELECT @rank:=0, @pre_con:= NULL) AS init
ORDER BY S.`continent`, S.`name`;

对rank进行分组如果continent是亚洲 把他放在亚洲列 别的同理

SELECT tmp.rank, IF(tmp.continent = 'America',tmp.NAME,NULL) AS `America`,
IF(tmp.continent = 'Asia', tmp.NAME,NULL) AS `Asia`,
IF(tmp.continent = 'Europe',tmp.NAME,NULL) AS `Europe`
FROM (SELECT S.`continent`, S.`name`, 
IF(S.`continent`=@pre_con, @rank:= @rank+1, @rank:=1) AS rank, 
@pre_con:= S.`continent` AS pre_con
FROM student2 AS S, (SELECT @rank:=0, @pre_con:= NULL) AS init
ORDER BY S.`continent`, S.`name`) AS tmp
GROUP BY tmp.rank; 

这样的结果 看下边这个就明白了

SELECT tmp.rank, IF(tmp.continent = 'America',tmp.NAME,NULL) AS `America`,
IF(tmp.continent = 'Asia', tmp.NAME,NULL) AS `Asia`,
IF(tmp.continent = 'Europe',tmp.NAME,NULL) AS `Europe`
FROM (SELECT S.`continent`, S.`name`, 
IF(S.`continent`=@pre_con, @rank:= @rank+1, @rank:=1) AS rank, 
@pre_con:= S.`continent` AS pre_con
FROM student2 AS S, (SELECT @rank:=0, @pre_con:= NULL) AS init
ORDER BY S.`continent`, S.`name`) AS tmp;

分组取得是每一组的第一行 所以造成了如上的结果

还是那个老问题 分组后最好与聚合函数连用 max min都行

SELECT tmp.rank, MAX(IF(tmp.continent = 'America',tmp.NAME,NULL)) AS `America`,
MAX(IF(tmp.continent = 'Asia', tmp.NAME,NULL)) AS `Asia`,
MAX(IF(tmp.continent = 'Europe',tmp.NAME,NULL)) AS `Europe`
FROM (SELECT S.`continent`, S.`name`, 
IF(S.`continent`=@pre_con, @rank:= @rank+1, @rank:=1) AS rank, 
@pre_con:= S.`continent` AS pre_con
FROM student2 AS S, (SELECT @rank:=0, @pre_con:= NULL) AS init
ORDER BY S.`continent`, S.`name`) AS tmp
GROUP BY tmp.rank;

分组排序还有自连接的方法

SELECT 
MAX(if(A.continent = 'America',A.NAME,NULL)) AS `America`,
MAX(if(A.continent = 'Asia',A.NAME,NULL)) AS `Asia`,
MAX(if(A.continent = 'Europe',A.NAME,NULL)) AS `Europe`
FROM
(
    SELECT S1.continent,S1.NAME,S1.row_id,COUNT(*) AS `trank`
    FROM 
    (
        SELECT S.*,@row_id:=(@row_id + 1) AS `row_id`
        FROM student AS S,(SELECT @row_id:=0) AS T
    ) AS S1 
    JOIN 
    (
        SELECT S.*,@n_row_id:=(@n_row_id + 1) AS `n_row_id`
        FROM student AS S,(SELECT @n_row_id:=0) AS T
    ) AS S2 
        ON (S1.continent = S2.continent AND (S1.NAME > S2.NAME OR (S1.NAME = S2.NAME AND S1.row_id >= S2.n_row_id)))
    group BY S1.continent,S1.NAME,S1.row_id
    order BY S1.continent,S1.NAME
) AS A
GROUP BY A.trank

你可能感兴趣的:(leetcode618. 学生地理信息报告(困难))