2015-05-02 6 views
1
driver [ dcode, dname ] 
route [ rcode, departure,arrival ] 
ride [ dcode, rcode ] 

SELECT dname FROM driver WHERE dcode IN (
    SELECT dcode FROM ride WHERE rcode IN (
     SELECT rcode FROM route WHERE departure = 'Barcelona' AND arrival = 'Madrid' 
    ) AND 
    rcode IN (
     SELECT rcode FROM route WHERE departure = 'Madrid' AND arrival= 'Barcelona' 
    ) 
); 

Речь идет о водителе, который делает оба маршрута: Мадрид-Барселона и Барселона-Мадрид, но мой запрос не работает.MySQL: double IN() statement

+0

Вызывает ли ваш запрос сообщение об ошибке или не возвращает никаких результатов? Я предполагаю, что существует несколько маршрутов с тем же rcode, который должен быть возвращен. – hines

ответ

0

не следует, что быть

SELECT dname FROM driver WHERE dcode IN (
    SELECT dcode FROM ride WHERE rcode IN (
     SELECT rcode FROM route WHERE departure = 'Barcelona' AND arrival =  
'Madrid' 
    ) OR 
    rcode IN (
     SELECT rcode FROM route WHERE departure = 'Madrid' AND arrival= 'Barcelona' 
    ) 
); 

OR вместо AND ...?

+0

Я думаю, что это зависит от того, как данные структурированы, поскольку требование заключается в том, что драйвер делает оба маршрута, а не только один из двух маршрутов. – hines

+0

@hines да, но если есть только один маршрут, madrid-barcelona и «return» отсутствует, вы не получите никакого результата или, вероятно, ошибку, так как список пуст. –

2

Ваш внутренний запрос (второй lvl) не возвращает результатов, потому что не может существовать rcode, который может находиться в первом подмножестве (B-> M) и во втором (M-> B). Пожалуйста, попробуйте следующее:

SELECT dname FROM driver WHERE dcode in 
(SELECT dcode 
FROM ride JOIN route 
ON (ride.rcode=route.rcode) 
WHERE route.departure = 'Barcelona' AND route.arrival = 'Madrid' 
) AND dcode in (
SELECT dcode 
FROM ride JOIN route 
ON (ride.rcode=route.rcode) 
WHERE route.departure = 'Madrid' AND route.arrival = 'Barcelona' 
) 
+0

Просто небольшая коррекция: условия только для одной из таблиц в инструкции с предложением 'join' должны быть в условии' where', а не в 'on'. Это может показаться nitpicking, но это делает запрос более читаемым, поскольку код sql лучше передает смысл. –

+0

Спасибо за подсказку, Зоар, я применил в своем редактировании ... но это действительно «просто читаемость»! ?? (Я часто нахожу себя «злоупотребляющим» предложением «on» как предложение «где» ... похоже, что вопрос эволюционирует :) – xerx593

+1

Я не знаю, будет ли это повлиять на производительность запроса каким-либо образом, но это может можно легко протестировать, сравнивая планы выполнения по запросам, которые идентичны другим, чем это конкретное изменение. В любом случае, читаемость кода не является чем-то, что нужно воспринимать легкомысленно. Всегда думайте о бедном ублюдке, который должен будет выполнить работу по обслуживанию вашего кода через 18 месяцев. Есть большая вероятность, что бедный ублюдок будет вам :-) –

0

Единственный сценарий, я могу думать о том, где IN не возвращает результаты, где он должен, это когда Eсть NULL RCODE в таблице. Попробуйте использовать следующий запрос

SELECT dname FROM driver WHERE dcode IN (
SELECT dcode FROM ride WHERE rcode IN (
    SELECT rcode FROM route WHERE departure = 'Barcelona' 
    AND arrival = 'Madrid' AND rcode IS NOT NULL 
) AND 
rcode IN (
    SELECT rcode FROM route WHERE departure = 'Madrid' 
    AND arrival= 'Barcelona' AND rcode IS NOT NULL 
) 
); 
2

where in неправильный подход, что вы ищете, where exists

SELECT dname FROM driver WHERE exists 
    (select dcode from route inner join ride on route.rcode = ride.rcode 
    where departure = 'Barcelona' and arrival = 'Madrid' and ride.dcode = driver.dcode 
) 
    and exists 
    (select dcode from route inner join ride on route.rcode = ride.rcode 
    where departure = 'Madrid' and arrival = 'Barcelona' and ride.dcode = driver.dcode 
) 

В качестве альтернативы, вы можете сделать это без каких-либо подзапросов вообще:

select dname 
    from driver d 
    inner join ride r 
     on d.dcode = r.dcode 
    inner join route rr 
     on r.rcode = rr.rcode 
     and rr.departure = 'Barcelona' 
     and rr.arrival = 'Madrid' 
    inner join ride r2 
     on d.dcode = r.dcode 
    inner join route rr2 
     on r2.rcode = rr2.rcode 
     and rr2.departure = 'Madrid' 
     and rr2.arrival = 'Barcelona'; 

demo here

+0

Я думаю, что «неправильный подход», это не «полная правда», а очень хорошие (правильные) запросы и демо! (+1) – xerx593

+0

Я бы сказал, что семантически 'in' неверно. –

1

Я думаю, что ap вы принимаете:

  1. Получить dcode для водителей на маршруте Барселона до Мадрида. Назовем это Set1.
  2. Получить dcode для водителей на маршруте Мадрид в Барселону. Назовем это Set2.
  3. Наконец, получить dname для водителей, dcode в обоих Set1 и SEt2.

Ваш запрос для Set1 является:

SELECT dcode FROM ride WHERE rcode IN (
    SELECT rcode FROM route WHERE departure = 'Barcelona' AND arrival = 'Madrid' 
) 

На тех же строках запроса для Set2 будет:

SELECT dcode FROM ride WHERE rcode IN (
    SELECT rcode FROM route WHERE departure = 'Madrid' AND arrival = 'Barcelona' 
) 

Наконец, вам нужно получить dcode, что это вSet1 & inSet2. Это будет перевести на запрос:

SELECT dname FROM driver WHERE 
dcode IN (
    SELECT dcode FROM ride WHERE rcode IN (
     SELECT rcode FROM route WHERE departure = 'Barcelona' AND arrival = 'Madrid' 
    ) 
) 
AND 
dcode IN (
    SELECT dcode FROM ride WHERE rcode IN (
     SELECT rcode FROM route WHERE departure = 'Madrid' AND arrival = 'Barcelona' 
    ) 
) 

В запросе, вместо того, чтобы искать dcode в двух сетах, вы искали rcode в двух сетах.

Рекомендации по улучшению: Для получения запросов dcode наборы, вы можете использовать внутреннее соединение вместо использования вложенных запросов. Пример:

SELECT dcode FROM ride INNER JOIN route ON ride.rcode = route.rcode 
WHERE departure = 'Barcelona' AND arrival = 'Madrid'