找到涉及从A到B的两辆公共汽车的路线

时间:2014-12-02 05:18:12

标签: mysql sql

来自sqlzoo的SQL中的问题: 查找包含两条巴士的路线,从Craiglockhart到Sighthill。 显示巴士号。和公司的第一辆公共汽车,转移的名称, 和巴士没有。第二辆公共汽车的公司。

这是我找到的代码,但它不起作用:

    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

9 个答案:

答案 0 :(得分:1)

当你遇到这样的大问题时,最好的做法是对它进行分区。从技术上讲,离开Craiglockhart的所有公共汽车最终都应该通过足够的转移到达Sighthill,但我们将自己限制为1次转移(因为这就是问题的措辞)

所以基本上,你需要找到一辆离开Craiglockhart的公共汽车和一辆到达Sighthill的公共汽车,你需要找到它们之间的所有交叉站点。

前两部分非常简单(你得到了那部分):

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相交的地方。

解决方案的初始部分同样简单;您需要获取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

值得注意的是,我使用过" WHERE EXISTS(...)"当你的运动明确暗示你应该使用自我联接时。如果您正在尝试学习,我不会给您完整的答案,所以请先尝试将其转换为自我联接;)

答案 1 :(得分:1)

SELECT S.num, S.company, S.name, T.num, T.company 
FROM 
    (SELECT DISTINCT a.num, a.company, sb.name 
     FROM route a JOIN route b ON (a.num = b.num and a.company = b.company) 
                  JOIN stops sa ON sa.id = a.stop 
                  JOIN stops sb ON sb.id = b.stop 
     WHERE sa.name = 'Craiglockhart' AND sb.name <> 'Craiglockhart'
)S

JOIN

    (SELECT x.num, x.company, sy.name 
     FROM route x JOIN route y ON (x.num = y.num and x.company = y.company) 
                  JOIN stops sx ON sx.id = x.stop 
                  JOIN stops sy ON sy.id = y.stop 
     WHERE sx.name = 'Lochend' AND sy.name <> 'Lochend'
    )T

ON (S.name = T.name)
ORDER BY S.num, S.name, T.num

答案 2 :(得分:1)

with p as (
select a.num,a.company,a.stop ,b.stop as des from route a join route b on a.num=b.num and a.company = b.company and a.stop = 53),
q as
(select a.num,a.company,a.stop as des,b.stop from route a join route b on a.num=b.num and a.company = b.company and b.stop = 147)
select p.num,p.company,r.name,q.num,q.company from p join q on p.des = q.des
join stops r on r.id = p.des order by p.num,r.name,q.num

答案 3 :(得分: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';

答案 4 :(得分:0)

SELECT distinct  a.num,a.company, stopb.name,  second.num, second.company
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)
  JOIN 
(
SELECT distinct  stopaa.name, aa.num, aa.company
FROM route aa JOIN route bb ON
  (aa.company=bb.company AND aa.num=bb.num)
  JOIN stops stopaa ON (aa.stop=stopaa.id)
  JOIN stops stopbb ON (bb.stop=stopbb.id)
  where stopbb.name ='Lochend'
) second on stopb.name = second.name
WHERE stopa.name='Craiglockhart'

答案 5 :(得分:0)

查找涉及两辆从Craiglockhart到Lochend的巴士的路线。 显示巴士号码还有第一班车的公司,换乘站的名称, 和公交车号和公司的第二辆公共汽车。 暗示: 两次自行加入,找到前往Craiglockhart和Lochend的巴士,然后在相匹配的车站加入。

SELECT DISTINCT one.num as FirstBus, one.company as FirstComp, one.name as Transfer, two.num as SecBus, two.company as SecComp

FROM

    (select distinct a.num, a.company, yy.name
     from route a join route b on (a.company=b.company and a.num=b.num) 
                  join stops xx on (xx.id=a.stop) 
                  join stops yy on (yy.id=b.stop)
     where xx.name='Craiglockhart' and yy.name<>'Lochend'
     ) AS one

JOIN

    (select distinct c.num, d.company, mm.name
     from route c join route d on (c.company=d.company and c.num=d.num) 
                  join stops mm on (mm.id=c.stop) 
                  join stops nn on (nn.id=d.stop)
     where mm.name <> 'Craiglockhart' and nn.name='Lochend'
     ) AS two

ON (two.name=one.name)

逻辑: 1.为那些拥有“ Craiglockhart”但没有“ Lochend”的人找到公司和公司; 2.为那些拥有“ Lochend”但没有“ Craiglockhart”的人找到公司和公司; 3.使用表“ stops”作为链接,从上述两个位置中找到共享的站点; 4.根据需要显示。 希望有帮助!

答案 6 :(得分:0)

提示“两次自我连接,找到前往Craiglockhart和Lochend的巴士,然后在相匹配的站点上行驶。”

首先,找到可以从stopa ='Craiglockhart'到达的站点。 其次,找到可以到达stopb ='Lochend'的停靠点。 然后,JOIN匹配停止。

Select first.num, first.company, first.name, second.num, second.company
From
    (Select Distinct a.num, a.company, stopb.name
    From route a JOIN route b ON (a.num=b.num AND a.company=b.company)
                 JOIN stops stopa ON stopa.id=a.stop
                 JOIN stops stopb ON stopb.id=b.stop
    Where stopa.name='Craiglockhart') first
JOIN
    (Select Distinct a.num, a.company, stopa.name
    From route a JOIN route b ON (a.num=b.num AND a.company=b.company)
                 JOIN stops stopa ON stopa.id=a.stop
                 JOIN stops stopb ON stopb.id=b.stop
    Where stopb.name='Lochend') second
Where first.name=second.name

答案 7 :(得分:0)

注意:这个想法是绕过这个问题:

任何enter image description here第一条线路,从the出发可以到达所有站点,这是中转站,在运营中找到通过站点的所有线路,找到后John Locke将要排队虽然没有陈述题目,但正确答案按行号、中转站排序

SELECT a.num, a.company,  stops.name,  d.num, d.company
FROM route a JOIN route b ON a.company = b.company AND a.num = b.num
JOIN stops ON b.stop = stops.id
JOIN route c ON c.stop = stops.id
JOIN route d ON c.company = d.company AND c.num = d.num
WHERE a.stop = (SELECT id FROM stops WHERE name = 'Craiglockhart')
AND d.stop = (SELECT id FROM stops WHERE name = 'Lochend')
ORDER BY a.num, stops.name, d.num

答案 8 :(得分:0)

SET SQL_BIG_SELECTS=1;

WITH sel1 AS (SELECT r1.num, r1.company, s2.name transferstop
FROM route r1
JOIN route r2 ON (r1.num=r2.num AND r1.company=r2.company)
JOIN stops s1 ON s1.id=r1.stop
JOIN stops s2 ON s2.id=r2.stop
WHERE s1.name = 'Craiglockhart'), 

sel2 AS (SELECT s1.name transferstop, r2.num, r2.company
FROM route r1
JOIN route r2 ON (r1.num=r2.num AND r1.company=r2.company)
JOIN stops s1 ON s1.id=r1.stop
JOIN stops s2 ON s2.id=r2.stop
WHERE s2.name = 'Lochend')

SELECT sel1.num, sel1.company, sel1.transferstop, sel2.num, sel2.company
  FROM sel1
  JOIN sel2 ON sel1.transferstop=sel2.transferstop
 ORDER BY 1,3,4
相关问题