2014-12-02 84 views
0

从sqlzoo到SQL的问题: 查找涉及两辆可从Craiglockhart前往Sighthill的巴士的路线。 显示巴士号码。公司为第一辆公交车,名称为转车站, 和公交车号。第二辆公共汽车的公司。找到涉及两辆可能从A到B的巴士的路线

这是我找到的代码,但它不会工作:

SELECT DISTINCT a.num, a.company, 
      trans1.name , c.num, c.company 
FROM route a JOIN route b 
ON (a.company = b.company AND a.num = b.num) 
JOIN (route c JOIN route d ON (c.company = d.company AND c.num= d.num)) 
JOIN stops start ON (a.stop = start.id) 
JOIN stops trans1 ON (b.stop = trans1.id) 
JOIN stops trans2 ON (c.stop = trans2.id) 
JOIN stops end ON (d.stop = end.id) 
WHERE start.name = 'Craiglockhart' AND end.name = 'Sighthill' 
      AND trans1.name = trans2.name 
ORDER BY a.num ASC , trans1.name 

The Table

+0

那么有什么不行? – leppie 2014-12-02 05:26:58

+0

我发现自己无法解决您的问题,可以通过提及您遇到的错误以及描述您的表结构来更加简明地解释问题。精明? – 2014-12-02 05:33:01

回答

0

我假设一个路由由一个简单的开始(这是pos属性)和结束,这是stop属性。希望这可以让你指向正确的方向。外部查询获取在Craiglockhart中启动的所有路由,并且内部查询获取以Sighthill结尾的所有路由,然后您加入第一个路由的结束与第二个路由的开始相同的两个路由。

SELECT r1.Num  AS FirstBusNo, 
      r1.Company AS FirstBusCompany, 
      Stops.Name AS Transfer, 
      r2.Num  AS SecondBusNo, 
      r2.Company AS SecondBusCompany 
     FROM Route r1 
INNER JOIN Stops trans 
     ON r1.Stop = trans.Id 
INNER JOIN (SELECT Num, Company, Pos 
      FROM Route, Stops 
      WHERE Id = stop 
      AND Name = 'Sighthill') r2 
     ON r1.stop = r2.pos 
    WHERE Stops.Name = 'Craiglockhart'; 
1

当你遇到这样的大问题时,最好的做法是对其进行分区。从技术上讲,所有出发Craiglockhart的公共汽车最终应达到Sighthill,并有足够的转移,但我们只限于1次转移(因为这是问题的原因)。

所以基本上,你需要找到一辆从Craiglockhart出发的公共汽车,以及一辆到达Sighthill的公共汽车,并且你需要找到它们之间的所有相交站点。

第2个部分是非常容易的(和你有那部分右):

SELECT DISTINCT num , company 
FROM route 
INNER JOIN stops ON stop = id 
WHERE name='Craiglockhart' 

SELECT DISTINCT num, company AS bus 
FROM route 
INNER JOIN stops ON stop = id 
WHERE name='Sighthill' 

从那里,你有离开Craiglockhart和所有所有公交车的列表巴士到达Sighthill。你唯一存在的问题是找到那两个相交的地方。

该解决方案的初始部分同样简单;您需要获取2辆巴士的名称以及停靠站的名称。

SELECT DISTINCT r1.num as NoFrom, r1.company CoFrom, name,r2.num as NoTo, r2.company CoTo 

这意味着你必须查询至少3个表

FROM stops 
INNER JOIN route r1 ON r1.stop = id 
INNER JOIN route r2 ON r2.stop = id 

所以,现在,你收集了所有可能的转会名单,你只需要过滤掉无用的。一个次优的方式做这将是这样的:

WHERE exists(
    SELECT 1 
    FROM route r3 
    INNER JOIN stops s1 ON r3.stop = s1.id 
    WHERE s1.name='Craiglockhart' AND r3.num = r1.num AND r3.company = r1.company) 

AND exists(
    SELECT 1 
    FROM route r4 
    INNER JOIN stops s2 ON r4.stop = s2.id 
    WHERE s1.name='Sighthill' AND r4.num = r2.num AND r4.company = r2.company) 

所以基本上做的一种方式将是:

SELECT DISTINCT r1.num as NoFrom, r1.company CoFrom, name, r2.num as NoTo, r2.company CoTo 
FROM stops 
INNER JOIN route r1 ON r1.stop = id 
INNER JOIN route r2 ON r2.stop = id 
WHERE exists(
    SELECT 1 
    FROM route r3 
    INNER JOIN stops s1 ON r3.stop = s1.id 
    WHERE s1.name='Craiglockhart' AND r3.num = r1.num AND r3.company = r1.company) 
AND exists(
    SELECT 1 
    FROM route r4 
    INNER JOIN stops s2 ON r4.stop = s2.id 
    WHERE s2.name='Sighthill' AND r4.num = r2.num AND r4.company = r2.company) 

Relevant SQLFiddle

有一件事值得一提的是,虽然我用“当存在(...)”时,你的练习明确暗示你应该使用自我连接。如果你想学习,我不会给你全部的答案,所以一定要去尝试把它转换成自己的联接;)

相关问题