最近面试遇到一个SQL题,复述如下:
SQL面试题
现在有两张表,结构如下:
学生表(student)
学号sid | 姓名name |
---|---|
1 | 张三 |
2 | 李四 |
3 | 王五 |
成绩表(score)
序号id | 学号sid | 科目subject | 分数score |
---|---|---|---|
1 | 1 | 语文 | 80 |
2 | 1 | 数学 | 90 |
3 | 2 | 语文 | 85 |
4 | 2 | 数学 | 100 |
5 | 3 | 语文 | 70 |
6 | 3 | 数学 | 60 |
- 写一个SQL,查出每个人的总分,并按倒序排列。输出字段如下:
姓名 | 总分 |
---|
- 最近学校要举行乒乓球运动会,准备采用循环赛,即每个人都与其他人都要比赛。写一个SQL列出每一场比赛的参赛人员,按顺序输出。
A组 | B组 |
---|
解答
- 考虑到成绩表中都是单科成绩,这里需要查询总成绩,那就先汇总计算总成绩;输出还要显示姓名,就在外层查询中关联查询姓名:
select s.name as '姓名', total as '总分' from student s left join (select sid, sum(score) as total from score group by sid
) t on s.id = t.sid order by total desc;
还可以直接关联查询:
select name as '姓名', sum(`score`) as '总分' from student u, `score` s
where u.id = s.sid group by s.sid order by sum(score) desc;
输出结果:
+----+-----+
|name|total|
+----+-----+
|李四 | 185|
|张三 | 170|
|赵六 | 138|
|王五 | 130|
+----+-----+
- 既然要输出全部循环数据,那可以考虑使用join
select a.name as 'A组', b.name as 'B组' from student a join student b on a.id!=b.id;
输出结果:
+----+-----+
|A组|B组|
+----+-----+
|赵六 |张三 |
|王五 |张三 |
|李四 |张三 |
|赵六 |李四 |
|王五 |李四 |
|张三 |李四 |
|赵六 |王五 |
|李四 |王五 |
|张三 |王五 |
|王五 |赵六 |
|李四 |赵六 |
|张三 |赵六 |
+----+-----+
注意,上述输出中包含两条张三和李四的记录,即每个人作为A组比赛一次,作为B组再比赛一次。如果两个人只比赛一次,可以考虑利用id大小进行去重。
select a.name as 'A组', b.name as 'B组' from student a join student b on a.id<b.id;
输出结果:
+----+-----+
|A组|B组|
+----+-----+
|张三|李四|
|张三|王五|
|张三|赵六|
|李四|王五|
|李四|赵六|
|王五|赵六|
+----+-----+
平时使用join写SQL时一般使用的等值连接,即在on后面紧跟着表的主键等于另一个表的某一列,很少使用不等于或其他比较操作符判断。在语法上,可以使用等值连接以外的方式,这种类型的连接被称为非等值连接或范围连接。但在实际应用中,使用非等值连接可能会导致较大的中间结果集,特别是在数据量大的情况下,这可能会影响查询性能。故不推荐使用!!!