Ответ 1
Вы можете попробовать SELECT DISTINCT
вместо SELECT
Я запускаю следующий запрос MySQL, чтобы найти автомобили, у которых нет руководств (и есть черные колеса и т.д.).
SELECT `cars`.* FROM `cars`
INNER JOIN wheels ON cars.id = wheels.car_id
LEFT OUTER JOIN manuals ON cars.id = manuals.car_id
WHERE (cars.created_at > '2010-09-09'
AND wheels.color = 'Black'
AND wheels.created_at < '2011-01-05'
AND manuals.car_id IS NULL)
Результаты запроса выглядят правильно, но он возвращает автомобиль с идентификатором 27 дважды. Как изменить запрос, чтобы все результаты были уникальными (без дубликатов)?
Вы можете попробовать SELECT DISTINCT
вместо SELECT
добавить group by cars.id
в конце запроса
НАПРИМЕР:
SELECT
cars
. * FROM cars
INNER JOIN колеса ON cars.id = wheels.car_id
Руководства LEFT OUTER JOIN ON cars.id = manuals.car_id
WHERE (cars.created_at > '2010-09-09'
AND wheels.color = 'Black'
AND wheels.created_at < '2011-01-05'
И manuals.car_id IS NULL)
GROUP BY cars.id
Код >
Предполагая, что cars.id
является уникальным первичным ключом, одно из этих объединений вызывает декартово произведение. То есть: wheels
или manuals
содержат более одного соответствия для cars.id = 27
.
Подзапросы часто являются хорошим инструментом для устранения декартовых произведений. В приведенном ниже примере ниже показаны два метода использования подзапросов.
Первый подзапрос гарантирует, что мы смотрим только на автомобили с черными колесами, где эта запись была создана до 01/05/2011. Предложение GROUP BY
гарантирует, что мы возвращаем только одну запись за w.car_id
.
Второй подзапрос (иногда называемый коррелированным подзапросом) гарантирует отсутствие ручного поиска для каждого автомобиля в основном запросе.
Не тестировалось, но передает идею:
SELECT `cars`.*
FROM `cars`
JOIN (
SELECT w.car_id
FROM wheels w
WHERE w.color = 'Black'
AND w.created_at < '2011-01-05'
GROUP BY w.car_id
) wheels
ON cars.id = wheels.car_id
WHERE
cars.created_at > '2010-09-09'
AND
NOT EXISTS (SELECT m.car_id FROM manuals m WHERE m.car_id = cars.id)