Reputation: 58244
I was recently working through the SQL tutorial for Self Join.
The table definitions given are quite simple:
stops(id, name)
route(num, company, pos, stop)
Here, the stop
attribute refers to the id
of the stop which is provided a name in the stops
table.
If you look at problem #10, I put in the following solution which the site indicates yields the correct results:
SELECT distinct a.num, a.company, bstops.name, e.num, e.company FROM route a
JOIN route b ON (a.company = b.company AND a.num = b.num)
JOIN stops bstops ON bstops.id = b.stop
JOIN
(SELECT c.company, c.num, d.stop as d_stop FROM route c
JOIN route d ON (c.company = d.company AND c.num = d.num)
WHERE c.stop = 213) e
ON e.d_stop = b.stop
WHERE a.stop = 53
Here, I already know that the id
for Craiglockhart
is 53
, and the id
for Sighthill
is 213
. All good so far.
But if I add an ORDER BY name
or ORDER BY bstops.name
to the query, the results change and more results are found:
SELECT distinct a.num, a.company, bstops.name, e.num, e.company FROM route a
JOIN route b ON (a.company = b.company AND a.num = b.num)
JOIN stops bstops ON bstops.id = b.stop
JOIN
(SELECT c.company, c.num, d.stop as d_stop FROM route c
JOIN route d ON (c.company = d.company AND c.num = d.num)
WHERE c.stop = 213) e
ON e.d_stop = b.stop
WHERE a.stop = 53 ORDER BY name
Specifically, for example, there are now 8 rows for London Road instead of just 4.
I've been playing with different queries trying to understand these results. Is there a reason ORDER BY
should change the actual results of the query besides sorting?
Upvotes: 3
Views: 273
Reputation: 33935
Unless Scottish buses stop at the same stop regardless of the direction of travel, then I think the answer provided by SQLZOO is wrong.
I think you can emulate their answer with this query...
SELECT a.num first_bus
, a.company first_company
, s1.name departing_from
, s2.name interchange
, d.num second_bus
, d.company second_company
, s3.name arriving_at
FROM route a
JOIN route b
ON b.num = a.num
AND b.pos <> a.pos
JOIN route c
ON c.stop = b.stop
JOIN route d
ON d.num = c.num
AND d.pos <> c.pos
JOIN stops s1
ON s1.id = a.stop
JOIN stops s2
ON s2.id = b.stop
JOIN stops s3
ON s3.id = d.stop
WHERE s1.name = 'Craiglockhart'
AND s3.name = 'Sighthill';
However, I think the correct answer would be the result of...
SELECT a.num first_bus
, a.company first_company
, s1.name departing_from
, s2.name interchange
, d.num second_bus
, d.company second_company
, s3.name arriving_at
FROM route a
JOIN route b
ON b.num = a.num
AND b.pos > a.pos
JOIN route c
ON c.stop = b.stop
JOIN route d
ON d.num = c.num
AND d.pos > c.pos
JOIN stops s1
ON s1.id = a.stop
JOIN stops s2
ON s2.id = b.stop
JOIN stops s3
ON s3.id = d.stop
WHERE s1.name = 'Craiglockhart'
AND s3.name = 'Sighthill';
Upvotes: 1
Reputation: 36630
You can limit the number of records returned by using the LIMIT
keyword on your query. I suppose that they are adding something like
... LIMIT 50 ...
to the query you are submitting, in order to avoid too many records to be returned.
Then, these first 50 records which are displayed can differ for different ORDER BY
expressions, since the records are ordered first and then the ordered result is limited.
Suppose you have this table
:
Id Name
--+-------
0 |Andreas
1 |Lurker
2 |Gordon
3 |John
Then,
SELECT * FROM table ORDER BY Id LIMIT 2;
Id Name
--+-------
0 |Andreas
1 |Lurker
while
SELECT * FROM table ORDER BY Name LIMIT 2;
Id Name
--+-------
0 |Andreas
2 |Gordon
Upvotes: 1