2012-07-28 9 views
10

mam 2 tabele jak poniżejMysql Wewnętrzne połączenie z warunkiem OR?

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 

ja zostać pobrany odstępu b/w miejscach other_table dla każdego rzędu. Oto, co wypróbowałem:

To nie zwraca wierszy, jeśli wartości są odwrotnie. Jak mogę przepisać powyższe zapytanie, aby uzyskać oczekiwany wynik? Czy powinienem zawrzeć warunek OR w klauzuli join? jak poniżej?

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) 

ale ta kwerenda Wyjaśnić mówi „Zasięg sprawdzana dla każdego rekordu”. .. czy to jest zła praktyka?

Wynik

-------------------------------------------------------- 
Id | fromLocid | toLocid | otherdata | distance 
-------------------------------------------------------- 
22 | 2  | 4  | xxxx  | 63 
78 | 3  | 5  | xxxx  | 70 

Oczekiwany wynik powinien być

----------------------------------------------------- 
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 
+0

już odpowiedziałeś na własne pytanie – Andreas

+0

, ale to drugie zapytanie mówi "Zakres sprawdzany dla każdego rekordu". .. czy to jest zła praktyka? – jane

+0

per se; mysql mówi ci tylko, że użył metody dostępu do zakresu, co oznacza, że ​​"nie ma dobrego indeksu do użycia" (http://dev.mysql.com/doc/refman/5.1/en/explain-output.html) ", co w rzeczywistości wynika z lub. – Andreas

Odpowiedz

1

Prawdopodobnie będzie to szybciej dołączyć tabelę odległości dwa razy jak

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 

, a następnie użyć IF celu ustalenia, który z nich wybrać

IF(ld1.fromLocid, ld1.distance, ld2.distance) as distance 
+0

Dzięki, spróbuję – jane

6

Możesz dołączyć na stole location_distance dwukrotnie stosując LEFT JOIN a następnie użyj funkcji COALESCE() aby przywrócić prawidłową wartość dla 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 

Zobacz SQL Fiddle with Demo

ta zwraca wynik:

| 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 | 
Powiązane problemy