我试过了http://sqlzoo.net/wiki/Self_join
Self Join: 找到从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
还有一个bug,就是我试
a.num
时ASC
的顺序不对
另外,当我将
DISTINCT
放在 c.num
之前时,它会显示错误。
我不能使用
group by
,因为它给出的行数太少。
为什么?
我对这个问题的解决方案: 我把问题分成两部分。
第一个子查询将是表 S(Start),它将获取所有 从“Craiglockhart”开始的路线第二个子查询将是 表 E(End),它将获取所有从 '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)
RE:排序“错误”,这是由于应用程序排序的方式造成的。它按字母顺序排序;所以 10 在 2 之前,等等。这篇文章 展示了一种使用 LENGTH() 进行“自然排序”的方法。
对于这个特定问题,我能够使用以下方法获得正确答案:
ORDER BY LENGTH(a.num), b.num, trans1.id, LENGTH(c.num), d.num;
如果您只想要不同的行,请使用关键字
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 的同义词。
我使用下面的代码。 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'
-- if you use MySQL engine, you need order by to pass the problem
order by a.num, stopb.name, d.num
正如@Eduardo06sp 评论的那样,我再次在 SQL Zoo 中测试此脚本,SQL Zoo 报告正确使用 Miscrosoft SQL 引擎,但报告错误的 MySQL 引擎没有
order by
.
如果有人能以人类的方式更深入地口头谈论这个问题,我会很高兴:)。
两地之间没有直达巴士 (在我的案例中,Craiglockhart 到 Lochend) 我通过先进行另一个查询得出了这个结论。 (如第6题)
所以我查询了第一个城市,然后查询了第二个城市,然后在匹配的站点上将它们连接在一起。之后,我们只需要选择所需的列即可。 这是我自己的答案:
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;
恕我直言...
在发布时,这里是更新的问题:
找到涉及从克雷格洛克哈特到洛兴德的两辆公共汽车的路线。 显示公交车号和第一辆公共汽车的公司,换乘站的名称, 和公共汽车号和第二辆公共汽车的公司。
请注意,目的地已更改为Lochend (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 重新组织输出以适应目标结果。
试试这个,它有效!
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
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
SELECT DISTINCT x.num,x.company,x.name,y.num,y.company
FROM
(
SELECT a.num as num,a.company as company,sb.name as name
FROM route a
JOIN route b
ON a.company = b.company AND a.num = b.num
JOIN stops sa
ON sa.id = a.stop
JOIN stops sb
ON sb.id = b.stop
WHERE
sa.name = 'Craiglockhart'
) x
JOIN
(
SELECT a.num as num, a.company as company,sb.name as name
FROM route a
JOIN route b
ON a.company = b.company AND a.num = b.num
JOIN stops sa
ON sa.id = a.stop
JOIN stops sb
ON sb.id = b.stop
WHERE sa.name = 'Sighthill'
) y
ON x.name = y.name
我使用下面的代码,网站接受它作为正确答案:
“一”代表第一班车; “second”代表第二辆公交车
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.
我通过运行以下查询得到了正确答案:
SELECT a.num,a.company,stopb.name,c.num,c.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 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' AND stopb.name=stopc.name
ORDER BY cast(a.num as char),stopb.name,cast(c.num as char)
请检查可能的解决方案:
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;
来源.