《SQL面试50题》刷题笔记 day7(知识点:函数group_concat()、开窗函数lead、内联结)

今天可以不用加班,出去溜达了一圈还略微迷路了。。哈哈哈

问题9 查询和"01"号的同学学习的课程完全相同的其他同学的信息(正确解法在下面)
这个题网上答案就是针对这个表的数据做查询,不能推广。

下面给出我搜到的一个答案,这个查询是通过选择与学号01的学生课程数量相同的学生 的信息。

select student.*
from student
where sid in (select sid from score group by sid having count(cid) = (select count(cid) from score where sid ='01')
 and sid<> '01');

这个题也不能用lead开窗函数做,因为也不能推广。

select * 
from student 
where sid in
 	(select b.sid from
 	(select sid, cid, lead(cid,1) over(partition by sid order by cid) cid2, 
 			lead(cid,2) over(partition by sid order by cid) cid3 from score) a,
 	(select sid, cid, lead(cid,1) over(partition by sid order by cid) cid2, 
 			lead(cid,2) over(partition by sid order by cid) cid3 from score) b
	where a.cid=b.cid and a.cid2=b.cid2 and a.cid3=b.cid3 and a.sid='01') 
 		--a表筛选出来学号sid=01的学生,b表找符合要求的学生
and sid not in('01')--排除掉学号01学生自身;

这个查询的思路是 考虑到学号01的学生以及课程表course只有cid为01 02 03的三门课,用lead开窗函数把所有学生的 每门课成绩作为新的字段,用学生01的每门课的成绩与其余行的对应成绩对比。
其中,由lead创建的新的表的语句和运行结果如下:

select sid, cid, 
lead(cid,1) over(partition by sid order by cid)cid2, 
lead(cid,2) over(partition by sid order by cid) cid3 
from score;
+-----+-----+------+------+
| sid | cid | cid2 | cid3 |
+-----+-----+------+------+
| 01  | 01  | 02   | 03   |
| 01  | 02  | 03   | NULL |
| 01  | 03  | NULL | NULL |
| 02  | 01  | 02   | 03   |
| 02  | 02  | 03   | NULL |
| 02  | 03  | NULL | NULL |
| 03  | 01  | 02   | 03   |
| 03  | 02  | 03   | NULL |
| 03  | 03  | NULL | NULL |
| 04  | 01  | 02   | 03   |
| 04  | 02  | 03   | NULL |
| 04  | 03  | NULL | NULL |
| 05  | 01  | 02   | NULL |
| 05  | 02  | NULL | NULL |
| 06  | 01  | 03   | NULL |
| 06  | 03  | NULL | NULL |
| 07  | 02  | 03   | NULL |
| 07  | 03  | NULL | NULL |
+-----+-----+------+------+

最后运行结果:

+-----+--------+------------+------+
| sid | sname  | sbirth     | ssex |
+-----+--------+------------+------+
| 02  | 钱电   | 1990-12-21 ||
| 03  | 孙风   | 1990-05-20 ||
| 04  | 李云   | 1990-08-06 ||
+-----+--------+------------+------+

后来看到一个新的函数叫 group_concat(),新解法有推广性。

select * 
from student s 
where sid in(
	select b.sid from
	(select sid, group_concat(cid order by cid) as cidstr 
	from score group by sid having sid = '01') a
	inner join
	(select sid, group_concat(cid order by cid) as cidstr 
	from score group by sid) b
	on a.cidstr = b.cidstr) and sid<>'01';

group_concat用法见如下链接:
mysql 分组内排——group_concat

+-----+--------+------------+------+
| sid | sname  | sbirth     | ssex |
+-----+--------+------------+------+
| 02  | 钱电   | 1990-12-21 ||
| 03  | 孙风   | 1990-05-20 ||
| 04  | 李云   | 1990-08-06 ||
+-----+--------+------------+------+

行转列做法

with t as
(select sid, max(case cid when '01' then 1 else 0 end) c01,
			max(case cid when '02' then 1 else 0 end) c02,
			max(case cid when '03' then 1 else 0 end) c03
			from score 
			group by sid)

select s.* from student s
join t t1 on s.sid=t1.sid
join t t2 on t2.c01=t1.c01 and t2.c02=t1.c02 and t2.c03=t1.c03
where t2.sid ='01' and s.sid <>'01';

问题10 查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩

select s.sid, s.sname,a.ave 
from student s,
(select sid, avg(sscore)  as ave from score where sscore<60 group by sid having count(sscore)>=2) a
where s.sid = a.sid;
select sc.sid, s.sname, avg(sc.sscore) ave
from student s 
join score sc
on s.sid=sc.sid and sc.sscore<60
group by sc.sid
having count(sc.sscore)>=2;

运行结果:

+-----+--------+---------------+
| sid | sname  | avg(b.sscore) |
+-----+--------+---------------+
| 04  | 李云   |       33.3333 |
| 06  | 吴兰   |       32.5000 |
+-----+--------+---------------+

问题11 检索"01"课程分数小于60,按课程“01”的分数降序排列的学生信息

select s.* from student s, score sc
where sc.sscore<60 and sc.cid='01'
and s.sid = sc.sid
order by sc.sscore desc;

我这几天解题好像习惯了where子句建立查询了哈哈哈
还有答案是基于join联结和子查询(查sid)给出的

select a.*, b.cid, b.sscore
from student as a 
inner join score b 
on a.sid=b.sid and b.cid='01'
where a.sid in
(select sid from score where sscore<60 order by sscore desc);

运行结果:

+-----+--------+------------+------+
| sid | sname  | sbirth     | ssex |
+-----+--------+------------+------+
| 04  | 李云   | 1990-08-06 ||
| 06  | 吴兰   | 1992-03-01 ||
+-----+--------+------------+------+

你可能感兴趣的:(SQL编程,mysql)