2014-12-02 49 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

有一件事值得一提的是,雖然我用「當存在(...)」時,你的練習明確暗示你應該使用自我連接。如果你想學習,我不會給你全部的答案,所以一定要去嘗試把它轉換成自己的聯接;)

相關問題