I have 2 tables like below
location_distance
----------------------------------------------
id | fromLocid | toLocid | distance
----------------------------------------------
1 | 3 | 5 | 70
2 | 6 | 8 | 15
3 | 2 | 4 | 63
...
other_table
--------------------------------------------
Id | fromLocid | toLocid | otherdata
--------------------------------------------
12 | 5 | 3 | xxxx
22 | 2 | 4 | xxxx
56 | 8 | 6 | xxxx
78 | 3 | 5 | xxxx
I would like to retrieve the distance b/w the locations in other_table for each row. Here's what i've tried
SELECT ot.*, ld.distance FROM other_table AS ot
INNER JOIN location_distance ld ON ld.fromLocid = ot.fromLocid AND ld.toLocid = ot.toLocid
This doesnt return the rows if the locations values are vice versa. How can i rewrite the above query to produce expected result? Should i inlude OR condition on the join clause? like below?
SELECT ot.*, ld.distance FROM other_table AS ot
INNER JOIN location_distance ld ON (ld.fromLocid = ot.fromLocid OR ld.fromLocid = ot.toLocid) AND (ld.toLocid = ot.fromLocid OR ld.toLocid = ot.fromLocid)
but this query Explain says "Range checked for each record". .. is this a bad practise?
Result
--------------------------------------------------------
Id | fromLocid | toLocid | otherdata | distance
--------------------------------------------------------
22 | 2 | 4 | xxxx | 63
78 | 3 | 5 | xxxx | 70
Expected Result should be
-----------------------------------------------------
Id | fromLocid | toLocid | otherdata | distance
-----------------------------------------------------
12 | 5 | 3 | xxxx | 70
22 | 2 | 4 | xxxx | 63
56 | 8 | 6 | xxxx | 15
78 | 3 | 5 | xxxx | 70
You can join on the location_distance
table twice using a LEFT JOIN
and then use the COALESCE()
function to return the correct value for the distance
:
select ot.id,
ot.fromlocid,
ot.tolocid,
ot.otherdata,
coalesce(ld1.distance, ld2.distance) distance
from other_table ot
left join location_distance ld1
on ld1.fromLocid = ot.toLocid
and ld1.toLocid = ot.fromLocid
left join location_distance ld2
on ld2.toLocid = ot.toLocid
and ld2.fromLocid = ot.fromLocid
See SQL Fiddle with Demo
This returns the result:
| ID | FROMLOCID | TOLOCID | OTHERDATA | DISTANCE |
---------------------------------------------------
| 12 | 5 | 3 | xxxx | 70 |
| 22 | 2 | 4 | xxxx | 63 |
| 56 | 8 | 6 | xxxx | 15 |
| 78 | 3 | 5 | xxxx | 70 |
It will probably be faster to join the distance table twice like
INNER JOIN location_distance ld1 ON ld1.fromLocid = ot.fromLocid AND ld1.toLocid = ot.toLocid
INNER JOIN location_distance ld2 ON ld2.toLocid = ot.fromLocid AND ld2.fromLocid = ot.toLocid
and then use an IF to determine which one to select
IF(ld1.fromLocid, ld1.distance, ld2.distance) as distance
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With