有什么问题,欢迎评论或私聊。转载请私聊博主,谢谢。
原题链接:https://sqlzoo.net/wiki/Self_join
其他题解连接:https://blog.csdn.net/aiqiyizz/article/details/109057732
文章目录
9 Self join
9.1 Summary
SELECT COUNT(*)
FROM stops
9.2
SELECT id
FROM stops
WHERE name = 'Craiglockhart'
9.3
我收回题意清晰的说法(没说过)。这题意(英文):Give the id and the name for the stops on the ‘4’ ‘LRT’ service. 问题太多了。
-
‘4’ ‘LRT’ service是什么???是route的num和company
能理解后,就能打出下面这种,步骤:找出对应stopid ⇒ \Rightarrow ⇒输出对应id和name
SELECT id, name FROM stops WHERE id IN ( SELECT stop FROM route WHERE num = 4 AND company = 'LRT' )
然后会发现Wrong Answer了,看了下数据发现一种诡异的排序方式。
-
原因是需要按照route的pos进行排序。被迫使用JOIN。以下正解
SELECT stops.id, stops.name FROM route INNER JOIN stops ON route.stop = stops.id WHERE route.num = 4 AND route.company = 'LRT' ORDER BY route.pos
9.4 Routes and stops
SELECT company, num, COUNT(*)
FROM route WHERE stop=149 OR stop=53
GROUP BY company, num
HAVING COUNT(*) = 2
9.5
题意又长又臭。例子已给all the places you can get to from Craiglockhart,你需要from Craiglockhart to London Road
也就是to的地点id为London Road的id即可。
SELECT a.company, a.num, a.stop, b.stop
FROM route a JOIN route b ON
(a.company=b.company AND a.num=b.num)
WHERE a.stop=53
AND b.stop=(SELECT id FROM stops WHERE name = 'London Road')
9.6
唯一有用的一句话:Change the query so that the services between ‘Craiglockhart’ and ‘London Road’ are shown.
程序没看懂直接加就correct了。
SELECT a.company, a.num, stopa.name, stopb.name
FROM route a JOIN route b ON
(a.company=b.company AND a.num=b.num)
JOIN stops stopa ON (a.stop=stopa.id)
JOIN stops stopb ON (b.stop=stopb.id)
WHERE stopa.name='Craiglockhart' AND stopb.name = 'London Road'
9.7 Using a self join
SELECT DISTINCT temp1.company, temp1.num
FROM route temp1,
route temp2
WHERE temp1.stop = 115
AND temp2.stop = 137
AND temp1.num = temp2.num
9.8
添加查id部分
SELECT DISTINCT temp1.company, temp1.num
FROM route temp1,
route temp2
WHERE temp1.stop = (SELECT id FROM stops WHERE name = 'Craiglockhart')
AND temp2.stop = (SELECT id FROM stops WHERE name = 'Tollcross')
AND temp1.num = temp2.num
9.9
有点麻烦,重构了一遍才过。
题目格式要求:stops.name,route.company,route.num
获取Craiglockhart车站的id ⇒ \Rightarrow ⇒通过id获取经过Craiglockhart车站的路线 ⇒ \Rightarrow ⇒找出在所需路线的城市,限制公司
-- 找出在所需路线的城市,限制公司
SELECT
stops.name,
route.company,
route.num
FROM
stops INNER JOIN route ON stops.id = route.stop
WHERE num IN
(
-- 通过id获取经过Craiglockhart车站的路线
SELECT
num
FROM
route
WHERE
stop = (
-- 获取Craiglockhart车站的id
SELECT id
FROM stops
WHERE name = 'Craiglockhart'
)
)
AND company = 'LRT'
9.10
最难一题,没有之一。值得一位sql新手来写一篇题解。
题意:求出Craiglockhart做两次公交车到达Lochend的路线。
输出要求:(第一次公交车编号,第一次公交车公司,中转站名称,第二次公交车编号,第二次公交车公司)
隐含要求:ORDER BY 第一次公交车编号, 中转站名称, 第二次公交车编号
题解:
首先要找出一轮公交车能到的车站和路线,这在上一题就做过了,这并不难。如下
SELECT
tempr2.num, tempr2.company, tempr2.stop
FROM
route tempr1
JOIN route tempr2 ON (
tempr1.num = tempr2.num
AND tempr1.company = tempr2.company
)
WHERE
tempr1.stop = (
SELECT
id
FROM
stops
WHERE
name = 'Craiglockhart'
)
麻烦的是要将两轮公交车的联系起来。
表格从上往下创建并连接成答案。
名称 | 作用 |
---|---|
tempr1 | Craiglockhart能前往的车站 |
tempr2 | 第一轮公交车能前往的车站以及经过的路线 |
stop | 提取出一轮公交车前往车站的名字 |
tempr3 | 在第一轮公交车前往的车站出发,能前往的第二轮公交车路线 |
tempr4 | 第二轮公交车能前往的车站以及到达Lochend经过的路线 |
如无法理解下面部分前后逻辑关系,可先看9.9部分
只看tempr1和tempr2部分,会发现tempr2是Craiglockhart能前往的城市;
只看tempr3和tempr4部分,会发现tempr4是能到达Lochend的城市;
tempr2和tempr3的部分,tempr3是从tempr2的城市出发能前往的城市。
限制tempr1为Craiglockhart出发的方法是给tempr1.stop添加where限制;限制tempr4为到达Lochend的方法是给tempr4.stop添加where限制。
代码部分,因为进行整合过,不是很容易理解。如果把每个部分的数据拆分出来,会容易理解些。
SELECT
tempr2.num num1,
tempr2.company,
stops.name,
tempr4.num num2,
tempr4.company
FROM
-- tempr1:Craiglockhart能前往的路线
route tempr1
-- tempr2:找出一次车的车站能抵达的车站
JOIN route tempr2 ON (
tempr1.num = tempr2.num
AND tempr1.company = tempr2.company
)
JOIN stops ON stops.id = tempr2.stop
-- tempr3:找出再坐一次车的车站能抵达的路线
JOIN route tempr3 ON tempr2.stop = tempr3.stop
-- tempr4:找出能抵达Lochend的车站
JOIN route tempr4 ON (
tempr4.num = tempr3.num
AND tempr4.company = tempr3.company
)
WHERE
-- Craiglockhart出发限制
tempr1.stop = (
SELECT
id
FROM
stops
WHERE
name = 'Craiglockhart'
)
AND
-- 到达Lochend限制
tempr4.stop = (
SELECT
id
FROM
stops
WHERE
name = 'Lochend'
)
ORDER BY
num1, name, num2