#mysql
#mysql
Вопрос:
У меня есть таблицы с отношением «один ко многим».
rental
------
id
book_date
prices
------
rental_id
type_id
value
Обычный запрос соединения даст результаты
select * from rental a join prices b on a.id = b.rental_id;
id book_date rental_id type_id value
1, 2016-10-04, 1, 8, 200
1, 2016-10-04, 1, 10, 300
2, 2016-10-04, 2, 8, 250
3, 2016-10-04, 3, 8, 200
3, 2016-10-04, 3, 10, 300
я хочу, чтобы, если запись цены имеет type_id = 10, то возьмите эту строку; если это не так, нужно взять строку с type_id = 8 . Результат, который я хочу:
1 2016-10-04 1 10 300
2 2016-10-04 2 8 250
3 2016-10-04 3 10 300
У меня есть этот запрос, но, похоже, он не работает в моем случае:
select * from rental a
join prices b
on a.id = b.rental_id and
( if(b.type_id = 10, b.type_id = 10, b.type_id = 8) )
ORDER BY a.id DESC LIMIT 20
Ответ №1:
я хочу, чтобы, если запись цены имеет type_id = 10, то она соединяется только с type_id 10, если нет, она соединяется с type_id = 8
Это означает, что запись с type_id 8 должна быть отброшена, если есть другая запись с type_id 10. Это «другое» вызывает другое СОЕДИНЕНИЕ, фактически ЛЕВОЕ СОЕДИНЕНИЕ, поскольку сравниваемая запись может не существовать:
SELECT a.*, b.* FROM rental a
JOIN prices b ON (a.id = b.rental_id)
LEFT JOIN prices check ON (a.id = check.rental_id AND check.type_id = 10)
WHERE b.type_id = 10 OR (b.type_id = 8 AND check.type_id IS NULL)
Это означает, что СОЕДИНЕНИЕ получит все типы 8 и типа 10; тогда ЛЕВОЕ СОЕДИНЕНИЕ сделает так, чтобы тип 8 принимался, только если нет соответствующего типа 10:
1 10 10
2 8 10 # discarded
2 10 10
3 8 NULL
4 15 NULL # discarded
4 8 NULL
Идентификатор 1 имеет только запись 10, оба запроса извлекают его, и он принимается. Идентификатор 2 имеет оба значения, поэтому запись 8-10 отбрасывается, потому что тип b равен 8, но тип c не равен NULL. Идентификатор 3 имеет только запись 8, поэтому 10-поисковое ЛЕВОЕ СОЕДИНЕНИЕ возвращает NULL, что соответствует второй части OR . Идентификатор 4 имеет идентификаторы типа_id 8 и 15, а 15 отбрасывается обеими частями OR.
Ответ №2:
если запись цены имеет type_id = 10, то она соединяется только с type_id 10, если нет, она соединяется с type_id = 8
Эта логика может быть применена путем выбора записи с максимальным type_id
значением для каждого rental_id
. Если это так, то вы можете просто добавить третье условие объединения, которое ограничит результирующий набор только записями, соответствующими этому дополнительному условию:
SELECT a.*, b.*
FROM rental a
INNER JOIN prices b
ON a.id = b.rental_id
INNER JOIN
(
SELECT rental_id,
CASE WHEN MAX(CASE WHEN type_id = 10 THEN 1 END) = 1 THEN 10
WHEN MAX(CASE WHEN type_id = 8 THEN 1 END) = 1 THEN 8
ELSE MAX(type_id)
END AS type_id
FROM prices
GROUP BY rental_id
) c
ON b.rental_id = c.rental_id AND
b.type_id = c.type_id
Перейдите по ссылке ниже для запуска демо:
SQLFiddle
Комментарии:
1. Извините, забыл упомянуть, на самом деле 10 не является максимальным значением type_id, есть несколько больших чисел, чем 10. Поэтому я думаю, что я не могу использовать максимум для выбора. Если существует 10, используйте 10, если нет, используйте 8 вместо этого. спасибо 🙂