LeetCode-618. 学生地理信息报告(困难)行转列
一所美国大学有来自亚洲、欧洲和美洲的学生,他们的地理信息存放在如下 student 表中。
| name | continent |
|--------|-----------|
| Jack | America |
| Pascal | Europe |
| Xi | Asia |
| Jane | America |
写一个查询语句实现对大洲(continent)列的 透视表 操作,使得每个学生按照姓名的字母顺序依次排列在对应的大洲下面。输出的标题应依次为美洲(America)、亚洲(Asia)和欧洲(Europe)。数据保证来自美洲的学生不少于来自亚洲或者欧洲的学生。
对于样例输入,它的对应输出是:
| America | Asia | Europe |
|---------|------|--------|
| Jack | Xi | Pascal |
| Jane | | |
进阶:如果不能确定哪个大洲的学生数最多,你可以写出一个查询去生成上述学生报告吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/students-report-by-geography
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
审题:根据原表写一个查询,生成新的结果。
数据保证来自美洲的不少于来自亚洲和欧洲的学生人数。所以排序可根据人数排出美洲,然后根据首字母排出亚欧州。
思考:查询相对简单,需要排序,和保证美洲人数多。
解题:
解法一
按continent字段分组,聚合,组内排序。可得。
+--------+-----------+
| name | continent |
+--------+-----------+
| Jack | America |
| Jane | America |
| Xi | Asia |
| Pascal | Europe |
+--------+-----------+
现在要行转列。
用America,Asia,Europe作为属性,Jack,Jane,Xi,Pascal作为值。
确定 Jack,Jane,Xi,Pascal 所在的数据行。
从 America 属性看,Jack在第1行,Jane在第2行;
从 Asia属性看,Xi在第1行。
从Europe属性看,Pascal在第1行。
最后一步,确定每个数据行中的数据。
按照 America,Asia,Europe 的顺序,
第1行:Jack Xi Pascal
第2行:Jane NULL NULL
合起来得出结果为:
| America | Asia | Europe |
|---------|------|--------|
| Jack | Xi | Pascal |
| Jane | | |
从上面的思路看,重点是两步:
第一,确定每个属性中各个数据所在的数据行。 其实是求每个数据的排名。
第二,确定每个数据行都有哪些数据。按照排名放置数据。
求每个数据的排名
求排名通常有两种方法,表自连接和用户变量法。
先讲表自连接法求排名
本题的输入表中,可能会存在多行相同的(name,continent)。
比如:
...
(A,B)
(A,B)
(A,B)
...
那么,仅用两个字段,用表自连接,无法确定每个(A,B)的排名。
将数据的行号作为第三个字段,用于区分相同的数据。
定义用户变量:@row_id——数据的行号,从1开始。
(SELECT @row_id:=0) AS T
给数字增加行号,结果表命名为S1:
(SELECT S.*,@row_id:=(@row_id + 1) AS `row_id`FROM student AS S,(SELECT @row_id:=0) AS T
) AS S1
S1表自连接算排名。
在同一个洲中,对每个人A,找出所有人B,满足条件:A.name > B.name 或 A.name = B.name 且 A.row_id > B.row_id。
意思是name字典序小的人排名在前,name字典序相同的人,行号小的排名在前。
S1表自连接也分join和left join。
用join,并且 “A.row_id > B.row_id ”改为“ A.row_id >= B.row_id ”。每个人都有排名,且排名从1开始。
用left join,每个人的排名从0开始。
此处用join,算排名的逻辑为:
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
尽管是S1表自连接,却引入了S2表。因为表名要唯一。
另外S2中的row_id也改为n_row_id。两者值相等。由于mysql中,S1表中的用户变量@row_id,会在表S2中被共享。如果在表S2中继续用@row_id表示行号,其值显然不对。才新增了变量@n_row_id作为行号。
此外,group by子句中,分组条件是:S1.continent,S1.NAME,S1.row_id。
因为要确定每个人的排名,分组依据应该是每个唯一的人。仅用 S1.continent,S1.NAME 不能唯一确定每个人,必须带上row_id。这才是前面引入row_id的意义。
再讲用户变量法求排名
用户变量法则相对简单。按continent升序,再按name升序。同一continent内,按name从小到大,排名从1开始。
用户变量:@trank——排名。@pre_con——前一行的continent。
排名逻辑如下,结果命名为表A
(SELECT S.*,@trank:=if(@pre_con = S.continent,@trank + 1,1) AS `trank`,@pre_con:=S.continent AS `pre`FROM student AS S,(SELECT @pre_con:=NULL,@trank:=0) AS TORDER BY S.continent,S.NAME
) AS A
按照排名放置数据
用上面的排名算法,得到的排名数据,格式为:name,continent,trank。
现要明确,
第1行数据,必须来自排名为1的所有行;
……
第i行数据, 必须来自排名为i的所有行;
这需要一个聚合操作,因此对排名数据,用group by分组.
每组内部,要根据continent确定name属于一个属性A.那么,此行属性A的值为name,其它属性值为NULL.
逻辑为:
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`
结合两种排名算法,最终结果为:
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_idorder BY S1.continent,S1.NAME
) AS A
GROUP BY A.trank
或者是:
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 S.*,@trank:=if(@pre_con = S.continent,@trank + 1,1) AS `trank`,@pre_con:=S.continent AS `pre`FROM student AS S,(SELECT @pre_con:=NULL,@trank:=0) AS TORDER BY S.continent,S.NAME
) AS A
GROUP BY A.trank
知识点:
LeetCode-618. 学生地理信息报告(困难)行转列相关推荐
- LeetCode MySQL 618. 学生地理信息报告(row_number)
文章目录 1. 题目 2. 解题 1. 题目 一所美国大学有来自亚洲.欧洲和美洲的学生,他们的地理信息存放在如下 student 表中. | name | continent | |--------| ...
- 「SQL面试题库」 No_42 学生地理信息报告
- LeetCode——552. 学生出勤记录 II(Student Attendance Record II)[困难]——分析及代码(Java)
LeetCode--552. 学生出勤记录 II[Student Attendance Record II][困难]--分析及代码[Java] 一.题目 二.分析及代码 1. 动态规划 (1)思路 ( ...
- 干货 | 清华大学刘知远 CCL 2018学生研讨会报告(附完整PPT下载)
来源:TsinghuaNLP 本文多图,建议阅读10分钟. 本文为你分享刘知远博士 CCL 2018学生研讨会报告内容,干货满满. 报告题目:文献综述与研究选题 报 告 人:刘知远 报告人简介: ...
- c语言作业重庆科技学院,C语言程序设计学生上机报告-NO3.doc
C语言程序设计学生上机报告-NO3.doc 重庆科技学院 上机实验报告(上机操作类) 课程名称 C 语 言 程 序 设 计 实验项目 循环结构程序设计(一) 机房名称 I313 上机时间 2017 年 ...
- Sql Server 行转列学习 根据学生表、课程表、学生成绩表统计每个学生的各科成绩和他的总成绩、平均成绩...
-------************************************************************* -------学习.测试行转列 ------- So ...
- 广州大学学生实验报告,数据结构实验,二叉树的操作与实现
广州大学学生实验报告 开课学院及实验室: 计算机科学与工程实验室 418 2022年10月3日 学院 计算机科学与网络工程 年级.专业.班 计科 姓名 Great Macro ...
- 广州大学数据库实验报告_广州大学学生实验报告.doc
广州大学学生实验报告 广州大学学生实验报告 开课学院及实验室: 地科院 室2015年5月6日 学院地理科学学院年级.专业.班资环122姓名曾鼎学号1201300045实验课程名称土地利用规划学成绩实验 ...
- JAVA计算机毕业设计学生实验报告管理系统Mybatis+源码+数据库+lw文档+系统+调试部署
JAVA计算机毕业设计学生实验报告管理系统Mybatis+源码+数据库+lw文档+系统+调试部署 JAVA计算机毕业设计学生实验报告管理系统Mybatis+源码+数据库+lw文档+系统+调试部署 本源 ...
- 广州大学学生实验报告,进程控制与进程通信
广州大学学生实验报告 开课学院及实验室: 计算机科学与网络工程学院 电子楼418B 20 ...
最新文章
- BZOJ 1176([Balkan2007]Mokia-CDQ分治-分治询问)
- ASP.NET 4新增功能(三) 对Web标准的支持和辅助功能的增强
- 美国0封伊朗已经6天了,伊石油出口真归零了吗?
- 用SMS2003部署Windows XP SP3:SMS2003系列之十
- 比dropout更好的方法_经营公司有更好的方法
- java已解密的登录请求_使用https协议解决掉顽固不化的已解密的登录请求
- CORBA版HelloWorld
- 关于金格电子签章的使用问题处理
- Java中判断String不为空的问题性能比较
- ILSVRC2015_DET.tar.gz下载地址
- mysql中用来取余数的函数是_mysql数学函数有哪些?
- 老男孩教育67期--day02--操作系统硬件知识
- 蓝牙耳机电脑玩游戏进入没声音设置
- MySQL 三星索引
- 不允许sam账户和共享的匿名枚举_不允许SAM 帐户匿名枚举是什么意思?
- Android聊天室(客户端)
- 升级生态主张:阿里云为千行百业带来了什么?
- Hive的安装与配置——第1关:Hive的安装与配置
- Docker Orchestration... What It Means and Why You Need It (Docker 编配 ...它是什么意思,为什么你会需要它?)
- b丅151组成的充电器电路_【图】可控硅BT136中文资料(参数,引脚及应用电路)