case when 子查询_SQL:多表查询

  • Post author:
  • Post category:其他



一、集合运算

集合运算:对满足同一规则的记录进行的加减等四则运算。


UNION以行

(纵向)为单位进行操作,而

JOIN以列

(横向)为单位进行操作。


1.表的加法(UNION)

两个表的结构相同,存放的数据不一样,可以使用表的加法将两个表的数据按行加在一起。

01df40e46449bd43c0c445aacf4a9e12.png
集合运算会除去重复的记录。

如果要在结果中保留重复行,只需要在UNION后面添加ALL关键字。

3f2252f83d64235701aadfc4ebeaaca0.png
ALL选项,在UNION之外的集合运算符中同样可以使用

注意事项:

  • 表的列数必须相同;
  • 列的类型必须一致;
  • 可以使用任何SELECT语句,但是ORDER BY子句只能在最后使用一次。

其他:

  • 表的减法:EXCEPT/MINUS(差集);
  • 选取表的公共部分:INTERSCECT(交集);
  • 上面两个语法与UNION相同,只是MYSQL暂不支持。这些运算的特征是

    以行方向

    为单位进行操作,不会导致列数的增减。


2.表的联结(JOIN)

表的联结就是通过表和表之间的关系,将表合并到一起。也就是将其他表中的列添加过来,进行

添加列

的运算。

64ed21e36896c570c3c3376a7e568782.png


常用联结:

1)内联结(INNER JOIN)

查找出同时存在于两张表中的数据,是应用最广泛的联结运算。

0f6933bc9eed76cd71bf2ba290e00c50.png

要点:

  • 对原表命名别名不是必须的,但是表名太长可能会影响SQL语句的可读性,因此建议使用别名;
  • ON是必不可少的,起到和WHERE相同的作用,书写时须在FROM和WHERE之间;需要指定多个键时,也可以使用AND和OR。

2)左联结(LEFT JOIN)和右联结(RIGHT JOIN)


左联结

:以左表为主表,将左侧表中的数据全部取出来。

621cf15010d188ae22855bf827a09b5b.png

19fbf2a8b83a776a9f9e43623a2759d3.png
在左联结的基础上,去掉了两个表中公共的部分


右联结

:将右侧表中的数据全部取出来

059e9c48e334916f036662358ae1508f.png

d1c294f819ab1518848b4536f97404d5.png
在右联结的基础上,去掉了两个表中公共的部分

3)交叉联结(CROSS JOIN)-笛卡尔积

将表中的每一行都与另一张表的每一行合并在一起。在实际业务中几乎不会使用。

5739eb2d7c64acf779f4c47014bb9e98.png
行数=左表行数*右表行数。上图未完全展示。

4)全联结(FULL JOIN)

返回两张表的所有行,如某一行有匹配就数据合并,没有就用空值填充。MYSQL不支持全联结。

5)多表联结

可以使用INNER JOIN进行添加,原则上联结表的数量是没有限制的。

eaa3ef7fc8809e7f8507eab004fc984a.png


总结

643375dc7d617f1c9f827750a855a950.png


二、联结应用案例

1.查询所有学生的学号、姓名、选课数和总成绩

6d3a7ac6b0d052d7b74243a078892c9a.png

2.查询平均成绩大于85分的所有学生的学号、姓名和平均成绩

8aae9527eacd69c45665b214a213bd23.png

3.查询学生的选课情况:学号,姓名,课程号,课程名称

4d29a901f31484c20501d31dae2b6888.png
多表联结


三、CASE表达式

CASE表达式用来解决复杂的查询问题,是一种条件判断的函数。CASE表达式会从最初的WHEN子句中的<判断表达式>求值开始执行。如果符合某个条件,就运行后面的THEN子句,若不符合条件,继续运行下一条WHEN子句,直到返回ELSE中的表达式,执行终止。CASE表达式是

SQL中极其重要

的功能。

CASE WHEN <判断表达式>THEN<表达式>

WHEN <判断表达式>THEN<表达式>

WHEN <判断表达式>THEN<表达式>…

ELSE<表达式>

END

举例:

1.在查询结果中显示成绩是否及格

b589e9d522725c0b68b74fd40dca8d39.png

2.查询出每门课程的及格人数和不及格人数

7f61fc6b274a0447faa6da5dbc24a93c.png

注意事项:

  • CASE表达式中的ELSE子句可以省略,但是防止漏读,还是建议写出来;
  • END不能省略;
  • CASE表达式可以写在SQL中任意地方。

3.使用分段[100-85]、[85-70]、[70-60]、[<60]来统计各科成绩。分别统计:课程号、课程名称和各分数段人数

ec83debb4a8a0e4a0356289dafa1ff00.png


四、练习:

SQLZOO

The JOIN operation

1.show thematchidandplayername for all goals scored by Germany. To identify German players, check for:teamid = 'GER'.
SELECT matchid,player FROM goal 
  WHERE teamid = 'GER';

2.Show id, stadium, team1, team2 for just game 1012.
SELECT id,stadium,team1,team2
  FROM game
WHERE id = '1012';

3.show the player, teamid, stadium and mdate for every German goal.
SELECT player,teamid,stadium,mdate
  FROM game INNER JOIN goal ON id=matchid
WHERE teamid = 'GER'; 
或 SELECT b.player,b.teamid,a.stadium,a.mdate
FROM game AS a INNER JOIN goal AS b
ON a.id=b.matchid
WHERE teamid = 'GER';

4.Show the team1, team2 and player for every goal scored by a player called Mario player LIKE 'Mario%'.
SELECT a.team1,a.team2,b.player
 FROM game AS a INNER JOIN goal AS b
ON a.id=b.matchid
WHERE b.player LIKE 'Mario%';

5.Show player, teamid, coach, gtime for all goals scored in the first 10 minutes gtime<=10.
SELECT a.player, a.teamid, b.coach, a.gtime
FROM goal AS a INNER JOIN eteam AS b
ON a.teamid=b.id
WHERE a.gtime<=10;

6.List the dates of the matches and the name of the team in which 'Fernando Santos' was the team1 coach.
SELECT a.mdate, b.teamname
FROM game AS a INNER JOIN eteam AS b 
ON a.team1 = b.id
WHERE coach = 'Fernando Santos';

7.List the player for every goal scored in a game where the stadium was 'National Stadium, Warsaw'.
SELECT a.player
FROM goal AS a INNER JOIN game AS b 
ON a.matchid = b.id
WHERE stadium =  'National Stadium, Warsaw';

8.show the name of all players who scored a goal against Germany.
SELECT DISTINCT b.player
  FROM game AS a INNER JOIN goal AS b ON a.id = b.matchid 
    WHERE (b.teamid = a.team1 AND a.team2='GER') OR (b.teamid = a.team2 AND a.team1='GER');

9.Show teamname and the total number of goals scored.
SELECT c.teamname, COUNT(b.player)
  FROM goal AS b INNER JOIN eteam AS c ON b.teamid = c.id
 GROUP BY c.teamname;

10.Show the stadium and the number of goals scored in each stadium.
SELECT a.stadium, COUNT(b.player)
  FROM game AS a INNER JOIN goal AS b ON a.id = b.matchid
 GROUP BY a.stadium;

11.For every match involving 'POL', show the matchid, date and the number of goals scored.
SELECT b.matchid,a.mdate,COUNT(b.player)
  FROM game AS a INNER JOIN goal AS b ON b.matchid = a.id 
 WHERE (team1 = 'POL' OR team2 = 'POL')
GROUP BY b.matchid,a.mdate;

12.For every match where 'GER' scored, show matchid, match date and the number of goals scored by 'GER'.
SELECT b.matchid,a.mdate,COUNT(b.player)
  FROM game AS a INNER JOIN goal AS b ON b.matchid = a.id 
 WHERE b.teamid = 'GER'
GROUP BY b.matchid,a.mdate;

13.List every match with the goals scored by each team as shown.  Sort your result by mdate, matchid, team1 and team2.
SELECT a.mdate,
a.team1,SUM(CASE WHEN a.team1=b.teamid THEN 1 ELSE 0 END) AS score1,
a.team2,SUM(CASE WHEN a.team2=b.teamid THEN 1 ELSE 0 END) AS score2
FROM game AS a LEFT JOIN goal AS b ON b.matchid = a.id
GROUP BY a.id,a.mdate,a.team1,a.team2
ORDER BY a.mdate,a.id,a.team1,a.team2;