我试过http://sqlzoo.net/wiki/Self_join
#10
的自加入会话#10:找到可以从Craiglockhart到Sighthill的两辆公共汽车的路线。显示公交车号码。和第一辆公共汽车的公司,转移的停止的名称,和公共汽车号码。第二辆公共汽车的公司。
这是我的代码:
SELECT 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
我知道输出会给你多行,如:
4 LRT London Road 35 LRT
4 LRT London Road 34 LRT
4 LRT London Road 35 LRT
4 LRT London Road 34 LRT
4 LRT London Road C5 SMT
你想要的地方:
4 LRT London Road 34 LRT
4 LRT London Road 35 LRT
4 LRT London Road 65 LRT
4 LRT London Road C5 SMT
还有一个错误,当我尝试a.num
时,ASC
的顺序不起作用。
此外,当我在DISTINCT
之前放置c.num
时,它显示错误。
不能使用group by,因为它会给你太少的行。
任何专家都可以提供帮助吗?
答案 0 :(得分:3)
我解决这个问题的方法: 我把问题分成两部分。
第一个子查询将是表S(开始),它将获得所有 从Craiglockhart'开始的路线第二个子查询将是 表E(结束),它将获得从中开始的所有路线 ' Sighthill'
现在表S和E都有公共路由,我通过使用每个表的id加入子查询来获得所有这些常见路由。 因为有重复的路线(相同:S.num,S.company,stops.name,E.num,E.company)我使用了DISTINCT。
SELECT DISTINCT S.num, S.company, stops.name, E.num, E.company
FROM
(SELECT a.company, a.num, b.stop
FROM route a JOIN route b ON (a.company=b.company AND a.num=b.num)
WHERE a.stop=(SELECT id FROM stops WHERE name= 'Craiglockhart')
)S
JOIN
(SELECT a.company, a.num, b.stop
FROM route a JOIN route b ON (a.company=b.company AND a.num=b.num)
WHERE a.stop=(SELECT id FROM stops WHERE name= 'Sighthill')
)E
ON (S.stop = E.stop)
JOIN stops ON(stops.id = S.stop)
答案 1 :(得分:1)
如果您只想要不同的行,请使用关键字DISTINCT
:
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
ALL和DISTINCT选项指定是否应该有重复的行 回。 ALL(默认值)指定所有匹配的行应该是 返回,包括重复。 DISTINCT指定删除 结果集中的重复行。指定两者都是错误的 选项。 DISTINCTROW是DISTINCT的同义词。
答案 2 :(得分:1)
RE:排序'bug',这是由于应用程序的排序方式。它按字母顺序排序;所以10在2之前出现,等等This article显示了一种使用LENGTH()进行“自然排序”的方法。
对于这个特殊问题,我能够使用以下方法得到正确的答案:
ruby-2.1.1 [ x86_64 ]
ruby-2.1.4 [ x86_64 ]
=* ruby-2.2.2 [ x86_64 ]
答案 3 :(得分:1)
如果有人可以以人类的口头更深入地谈论这个问题,我会很高兴。
两个地方之间没有直达巴士 (在我的情况下,克雷格洛克哈特飞往洛亨德) 我通过首先进行另一个查询得出了这个结论。 (就像第六个问题一样)
所以我先查询了第一个城市,然后又查询了第二个城市,然后在他们匹配的站点上将它们合并在一起。之后,我们需要选择所需的列。 这是我自己的答案:
SELECT
firstbus.busnumber AS 'num',
firstbus.company,
secondbus.transfer AS 'name',
secondbus.busnumber AS 'num',
secondbus.company
FROM (
SELECT r1.num AS 'busnumber',
r1.company AS 'company',
r2.stop AS 'stopp'
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'
) firstbus
JOIN
(
SELECT s1.name AS 'transfer',
r1.num AS 'busnumber',
r1.company AS 'company',
r1.stop AS 'stopp',
r1.pos AS 'pos'
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'
) secondbus
ON firstbus.stopp = secondbus.stopp
ORDER BY firstbus.busnumber, name, 4;
以我所有的敬意...
答案 4 :(得分:1)
发布时,这是更新的问题:
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.
请注意,目的地已更改为午餐(147)。以下查询在发布时产生正确的结果:
SELECT DISTINCT bus1.num, bus1.company, transfer.name, bus2.num, bus2.company
FROM route bus1 JOIN route midA ON (bus1.num = midA.num AND bus1.company = midA.company)
JOIN route midD ON (midA.stop = midD.stop)
JOIN route bus2 ON (midD.num = bus2.num AND midD.company= bus2.company)
JOIN stops transfer ON (midA.stop = transfer.id)
WHERE bus1.stop = 53 AND bus2.stop = 147
ORDER BY bus1.company, bus1.num, midA.stop, bus2.num
请注意,最后的ORDER BY会重新组织输出以适合目标结果。
答案 5 :(得分:0)
试试这个,它有效!
SELECT DISTINCT a.num, a.company,
trans1.name, d.num, d.company
FROM route a JOIN route b
ON (a.company = b.company AND a.num = b.num)
JOIN route c ON (b.stop=c.stop AND b.num!=c.num)
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 length(a.num), a.num
答案 6 :(得分:0)
SELECT DISTINCT sub1.num,
sub1.company,
name,
sub2.num,
sub2.company
FROM (SELECT r1.num,
r1.company,
r1.stop AS first,
r2.stop AS mid
FROM route r1
JOIN route r2
ON r1.num = r2.num
AND r1.company = r2.company
WHERE r1.stop = (SELECT id
FROM stops
WHERE name = 'Craiglockhart'))sub1
JOIN (SELECT r3.num,
r3.company,
r3.stop AS mid2,
r4.stop AS dest
FROM route r3
JOIN route r4
ON r3.num = r4.num
AND r3.company = r4.company
WHERE r4.stop = (SELECT id
FROM stops
WHERE name = 'Sighthill'))sub2
ON sub1.mid = sub2.mid2
JOIN stops
ON id = sub1.mid
答案 7 :(得分:0)
e->add_handler
答案 8 :(得分:0)
我使用下面的代码。 a,b用于第一条总线,c,d用于第二条总线。 和b,c使用相同的挡块进行连接。
SELECT a.num, a.company, stopb.name, d.num, d.company
FROM route a JOIN route b ON (a.company = b.company AND a.num = b.num)
JOIN route c ON (b.stop = c.stop)
JOIN route d ON (d.company = c.company AND c.num = d.num)
JOIN stops stopa ON a.stop = stopa.id
JOIN stops stopb ON b.stop = stopb.id
JOIN stops stopc ON c.stop = stopc.id
JOIN stops stopd ON d.stop = stopd.id
WHERE stopa.name = 'Craiglockhart'
AND stopd.name = 'Lochend'
答案 9 :(得分:0)
我使用下面的代码,网站接受了它作为正确答案:
“一个”代表第一辆公共汽车; “第二”代表第二条总线。
select distinct
#one.start,
#two.end,
one.num,
one.company,
one.transfer as name,
two.num,
two.company
from
(select distinct -- make sure you use select distinct here or else you will get an error "The SELECT would examine more than MAX_JOIN_SIZE rows”
a.num,
a.company,
stopsa.name as start,
stopsb.name as transfer,
stopsb.id as transferid
from route a
inner join route b
on (a.num = b.num and a.company = b.company)
join stops stopsa on (stopsa.id = a.stop)
join stops stopsb on (stopsb.id = b.stop)
where stopsa.name = 'Craiglockhart' and stopsb.name != 'Lochend' -- we don't want the first bus to lead us directly to 'Lochend'
) one
join
(select distinct
c.num,
c.company,
stopsc.name as transfer,
stopsd.name as end
from route c
inner join route d
on c.num = d.num and c.company = d.company
join stops stopsc on stopsc.id = c.stop
join stops stopsd on stopsd.id = d.stop
where stopsd.name = 'Lochend' and stopsc.name != 'Craiglockhart' -- we don't want the second bus to go from Craiglockhart to Lochend
) two
on two.transfer = one.transfer -- first bus and second bus' overlap --> the transfer stop!
ORDER BY one.company, one.num, one.transfer, two.num -- i addded this final statement just to tailor my code to fit the correct answer. think this is a bug with sqlzoo.
答案 10 :(得分:-1)
请检查可能的解决方案:
SELECT distinct StartOfR1.num, StartOfR1.company, Xfer.name xfer_name, EndOfR2.num, EndOfR2.company
FROM stops Start, stops Xfer, stops Finish, route StartOfR1, route EndOfR1, route StartOfR2, route EndOfR2
WHERE Start.name='Craiglockhart' AND Finish.name='Sighthill' AND StartOfR1.stop= Start.id -- R1 actually visits Start
AND EndOfR1.num = StartOfR1.num -- no transfer on the same route
AND EndOfR1.stop= StartOfR2.stop -- R2 starts where R1 ends
AND EndOfR1.num != StartOfR2.num -- R1 and R2 are not the same route
AND EndOfR1.stop = Xfer.id-- R1 changes to R2
AND EndOfR2.company = StartOfR2.company -- R1 changes bus to R2
AND EndOfR2.num = StartOfR2.num -- two stops on the same route
AND EndOfR2.stop = Finish.id -- R2 actually visits Finish;