1、The_JOIN_operation
网址:https://sqlzoo.net/wiki/The_JOIN_operation
涉及到的表及其关系说明如下:
8、The example query shows all goals scored in the Germany-Greece quarterfinal.Instead show the name of all players who scored a goal against Germany.
HINT(提示):Select goals scored only by non-German players in matches where GER was the id of either team1 or team2.
You can use teamid!=‘GER’ to prevent listing German players.
You can use DISTINCT to stop players being listed twice.
这道题目本身不难,就是英语不太过关,看了半天题目才看懂…
Instead show the name of all players who scored a goal against Germany.
翻译:而是显示所有在对德国队比赛中进球的球员的名字。
SELECT distinct(player)
FROM game
JOIN goal ON matchid = id
WHERE (team1='GER' or team2='GER') AND teamid!='GER'
13、List every match with the goals scored by each team as shown. This will use “CASE WHEN” which has not been explained in any previous exercises.
Notice in the query given every goal is listed. If it was a team1 goal then a 1 appears in score1, otherwise there is a 0. You could SUM this column to get a count of the goals scored by team1. Sort your result by mdate, matchid, team1 and team2.
case when…then…的用法介绍
# 原来CASE WHEN...THEN和SUM组合使用的语法是这样,学到了
SELECT mdate,team1,
SUM(CASE WHEN teamid=team1 THEN 1 ELSE 0 END) as score1,
team2,
SUM(CASE WHEN teamid=team2 THEN 1 ELSE 0 END) as score2
FROM game LEFT JOIN goal ON matchid = id group by mdate,matchid,team1,team2
2、More_JOIN_operations
网址:https://sqlzoo.net/wiki/More_JOIN_operations.
对需要用到的表的介绍:https://sqlzoo.net/wiki/More_details_about_the_database.
6.Obtain the cast list for ‘Casablanca’.
what is a cast list?The cast list is the names of the actors who were in the movie.
Use movieid=11768, (or whatever value you got from the previous question)
# 可以使用嵌套查询
SELECT a.name
FROM actor a
JOIN casting c ON a.id=c.actorid
WHERE c.movieid=(SELECT id
FROM movie
WHERE title='Casablanca')
7.Obtain the cast list for the film ‘Alien’.
# 原理与上面一题一样,这里可以用另一种方式:因为涉及到三张表,可以三表join
SELECT a.name
FROM actor a JOIN casting c ON a.id=c.actorid
JOIN movie m ON m.id=c.movieid
WHERE m.title='Alien'
12.List the film title and the leading actor for all of the films ‘Julie Andrews’ played in.
错误做法:
SELECT m.title,a.name
FROM casting c JOIN movie m ON m.id=c.movieid
JOIN actor a ON a.id=c.actorid
WHERE a.name='Julie Andrews'
以上做法筛选出来的只是Julie Andrews参演的所有电影,并不能找到对应的leading actor。
正确做法:
# 通过where条件从casting表中找出Julie Andrews参演的所有电影的movieid(即c.movieid),
# 再在表连接中限制c.ord=1,查询出m.title和a.name
SELECT m.title,a.name
FROM casting c
JOIN movie m ON m.id=c.movieid AND c.ord=1
JOIN actor a ON a.id=c.actorid
WHERE c.movieid IN (SELECT movieid FROM casting
JOIN actor ON id=actorid
WHERE name='Julie Andrews')
13.Obtain a list, in alphabetical order, of actors who’ve had at least 15 starring roles.
SELECT a.name
FROM actor a JOIN casting c ON a.id=c.actorid
WHERE c.ord=1 GROUP BY a.name HAVING COUNT(*)>=15
14.List the films released in the year 1978 ordered by the number of actors in the cast, then by title.
注意: order by后面也可以跟聚合函数。
SELECT m.title,COUNT(c.actorid)
FROM movie m JOIN casting c ON m.id=c.movieid
WHERE m.yr=1978
GROUP BY m.title
ORDER BY COUNT(c.actorid) DESC,m.title
15.List all the people who have worked with ‘Art Garfunkel’.
# 注意:最后要加AND a.name!='Art Garfunkel'
SELECT a.name
FROM casting c JOIN actor a ON c.actorid=a.id
JOIN movie m ON c.movieid=m.id
WHERE c.movieid IN
(SELECT movieid
FROM casting
JOIN actor ON actorid=id
WHERE name='Art Garfunkel')
AND a.name!='Art Garfunkel'
3、COALESCE 和 IFNULL
网址:https://sqlzoo.net/wiki/COALESCE
COALESCE是一个函数,返回传入的参数中第一个非NULL的值,可以接受两个或两个以上参数(上限个数目前还不清楚)。
如:
SELECT COALESCE(NULL,1); -->1
SELECT COALESCE(NULL, NULL, 1); --> 1
SELECT COALESCE(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1); --> 1
如果传入的参数所有都是null,则返回null,比如
SELECT COALESCE(NULL, NULL, NULL, NULL); --> NULL
**这个函数使用的场合为:假如某个字段默认是null,你想其返回的不是null,而是比如0或其他值,可以使用这个函数: **
SELECT COALESCE(field_name,0) as value from table;
类似函数:
IFNULL(x,y):如果x为NULL,则返回后面设置的y,否则返回x,一般使用场合同上(只能用于mysql数据库中);
HINT(提示):
1)在所有数据库中只要有NULL参与的数学运算,最终结果就是NULL,为避免这个现象,需要使用IFNULL()或者COALESCE()函数;
2)在数据库中,NULL就是空,啥值都没有,而不是显示为NULL。
4、NULLIF和NVL
1. NULLIF(x,y):如果x等于y,则返回NULL,否则返回x;
2.NVL(x,y) :与IFNULL()函数用法一致,只是其只能用于orcale数据库中。
以上各个函数在不同数据库中的支持情况总结:
函数名 | Oracle | Mysql | SqlServer |
---|---|---|---|
COALESCE(x,y,z) | √ | √ | √ |
IFNULL(x,y,z) | √ | ||
NVL(x,y,z) | √ | ||
NULLIF(x,y) | √ | √ | √ |
在这里再附上SQL的函数一览表:https://sqlzoo.net/wiki/FUNCTIONS
5、Self_join
网址:https://sqlzoo.net/wiki/Self_join
所需要用到的表:
stops(id, name)
route(num, company, pos, stop)
字段详细描述:https://sqlzoo.net/wiki/Edinburgh_Buses
3.Give the id and the name for the stops on the ‘4’ ‘LRT’ service.
# 这里需要注意的是在route表中num的类型为char型,
# 所以要用r.num='4',而不是r.num=4
SELECT s.id,s.name
FROM stops s
JOIN route r ON s.id=r.stop
WHERE r.company='LRT' AND r.num='4'
7.Give a list of all the services which connect stops 115 and 137 (‘Haymarket’ and ‘Leith’)
SELECT a.company, a.num
FROM route a JOIN route b ON
(a.company=b.company AND a.num=b.num)
WHERE a.stop='115' and b.stop='137'
以上筛选会有多条一样的数据,虽然显示的数据a.company和a.num一样,但是实际上a.pos和b.pos不一样,这是因为一条路线上可能会多次访问同一个站点,所以a.company和a.num一样,而实际在该路线的停止顺序(即a.pos和b.pos)不一样,所以需要去重。
去重方法:
法1.通过使用GROUP BY a.company,a.num达到分组后自动去重的目的
SELECT a.company, a.num
FROM route a
JOIN route b ON (a.company=b.company AND a.num=b.num)
WHERE a.stop=115 and b.stop=137
GROUP BY a.company,a.num
法2.使用distinct关键字
错误写法:
SELECT a.company,distinct a.num
FROM route a
JOIN route b ON (a.company=b.company AND a.num=b.num)
WHERE a.stop=115 and b.stop=137
正确写法:
SELECT distinct a.company,a.num
FROM route a
JOIN route b ON (a.company=b.company AND a.num=b.num)
WHERE a.stop=115 and b.stop=137
注意:distinct只能出现在所有字段的最前方表示对后面所有字段进行联合去除重复记录。
9.Give a distinct list of the stops which may be reached from ‘Craiglockhart’ by taking one bus, including ‘Craiglockhart’ itself, offered by the LRT company. Include the company and bus no. of the relevant services.
SELECT st.name,a.company,a.num
FROM route a JOIN route b ON a.company=b.company AND a.num=b.num
JOIN stops s ON s.id=a.stop
JOIN stops st ON st.id=b.stop
WHERE s.name='Craiglockhart' AND a.company='LRT'
10.Find the routes involving two buses that can go from Craiglockhart to Lochend.
Show the bus no. and company for the first bus, the name of the stop for the transfer,
and the bus no. and company for the second bus.
哇,感觉最一题的难度突然就提起来了。想了一会,没有十分明确的思路就在CSDN上查了一下,发现了https://blog.csdn.net/weixin_42012759/article/details/112873521
上面这篇博文里有十分详细的解释,看了前面一半的讲解加上后面有博主的评论就有了思路。
题目解析:
题目的意思是求解Craiglockhart——>Lochend的含有中转站的大巴路线,查询后显示起始站的num,起始站的company,中转站的name,终点站的num,终点站的company。
步骤:
1、查询出起始站为name=Craiglockhart的所有车,将数据存入虚拟表a;
2、查询出终点站为name=Lochend站的所有车,将数据存入虚拟表b;
3、进行两表连接,连接条件为a表的终点站等于b表的起始站(即作为中转站)。
SELECT a.num firstNum, a.company firstCom, a.name transfer , b.num secondNum, b.company secondCom
FROM(SELECT r1.num, r1.company, s2.name
FROM route r1 JOIN route r2 ON r1.company = r2.company
AND r1.num = r2.num
JOIN stops s1 ON r1.stop = s1.id
JOIN stops s2 ON r2.stop = s2.id
WHERE s1.name = 'Craiglockhart') a
JOIN(SELECT r2.num, r2.company, s1.name
FROM route r1 JOIN route r2 ON r1.company = r2.company
AND r1.num = r2.num
JOIN stops s1 ON r1.stop = s1.id
JOIN stops s2 ON r2.stop = s2.id
WHERE s2.name = 'Lochend') b
ON a.name = b.name
GROUP BY firstNum, firstCom, transfer, secondNum, secondCom
注意:查询完后需要使用GROUP BY分组才能得到Correct answer!
6、结语
到此为止Sqlzoo上的题目就全部刷完啦(完结撒花~( ̄▽ ̄)~ )!感觉这么做下来感觉Sqlzoo既是一个练题的网站,也是一个对SQL的基础学习的网站,里面每个语句、函数都有很详尽的解释(虽然全英文式有的时候读得有点头大,也算是对英文阅读的一种锻炼了!( ̄ェ ̄;)。目前练到的只是SQL的基础,还要再接再厉!