Ответ 1
SELECT * FROM film WHERE id IN
(SELECT filmid FROM film_rating_report WHERE rating = 'GE');
должен работать
У меня в настоящее время есть 2 таблицы mysql в моей db
Film
и Film_Ratings_Report
Первичный ключ для фильма - filmid
, который используется для идентификации номиналов пленки в таблице Film_Ratings_Report
.
Я хотел бы знать, возможно ли его использование MYSQL-запроса только для поиска таблицы рейтингов и сбора всех идентификаторов фильмов, которые соответствуют определенным критериям, затем используйте выбранные идентификаторы, чтобы получить названия фильмов из таблицы Film. Ниже приведен запрос MYSQL Im, который не работает:
SELECT *
FROM film
UNION SELECT filmid
FROM film_rating_report
WHERE rating = 'GE'
LIMIT 0,0
Я относительно зеленый для MYSQL и буду признателен за любую помощь в этом.
Спасибо в Advance
SELECT * FROM film WHERE id IN
(SELECT filmid FROM film_rating_report WHERE rating = 'GE');
должен работать
Кажется, вы хотите полу-соединение, например. соединение, в котором необходимы только данные из одной из двух соединенных таблиц. В этом случае все строки из film
, для которых есть соответствующая строка в film_rating_report
, которая имеет желаемое условие (rating = 'GE'
).
Это не совсем эквивалентно обычному соединению, потому что даже если во второй таблице есть 2 (или более) строки (2 оценки фильма, как с 'GE'
), мы все равно хотим, чтобы фильм отображался один раз, а не дважды (или более раз), как это было бы показано с обычным соединением.
Существуют различные способы написания полусоединения и самые популярные:
используя EXISTS
коррелированный подзапрос (@Justin answer):
SELECT t1.*
FROM film t1
WHERE EXISTS (SELECT filmid
FROM film_rating_report t2
WHERE t2.rating = 'GE'
AND t2.filmid = t1.id);
используя IN
(некоррелированный) подзапрос (@SG 86 answer):
(это следует использовать с особой осторожностью, поскольку оно может возвращать неожиданные результаты - или вообще ничего), если соединительные столбцы (два filmid
в этом случае) являются Nullable)
SELECT *
FROM film
WHERE id IN
( SELECT filmid
FROM film_rating_report
WHERE rating = 'GE'
);
используя обычный JOIN
с GROUP BY
, чтобы избежать дублирования строк в результатах (@Tomas ответ):
(и обратите внимание, что это конкретное использование GROUP BY
работает только в MySQL и в последних версиях Postgres, если вы когда-либо захотите написать аналогичный запрос в другой СУБД, вам нужно будет включить все столбцы: GROUP BY f.filmid, f.title, f.director, ...
)
SELECT f.*
FROM film AS f
JOIN film_rating_report AS frr
ON f.filmid = frr.filmid
WHERE frr.rating = 'GE'
GROUP BY f.filmid ;
Вариант ответа @Tomas'es, где GROUP BY
выполняется на производной таблице, а затем JOIN
:
SELECT f.*
FROM film AS f
JOIN
( SELECT filmid
FROM film_rating_report
WHERE rating = 'GE'
GROUP BY filmid
) AS frr
ON f.filmid = frr.filmid ;
Какой из них использовать, зависит от СУБД и конкретной версии, которую вы используете (например, IN
подзапросы следует избегать в большинстве версий MySQL, поскольку они могут создавать неэффективные планы выполнения), ваши конкретные размеры таблиц, распределение, индексы и т.д.
Обычно я предпочитаю решение EXISTS
, но никогда не боится сначала тестировать различные запросы с размерами таблиц, которые у вас есть или ожидаются в будущем, и попытаться найти лучшую комбинацию запросов-индексов для вашего случая.
Дополнение: если существует уникальное ограничение на комбинацию film_rating_report (filmid, rating)
, что означает, что ни один фильм никогда не получит два одинаковых рейтинга, или если на film_rating_report (filmid)
существует еще более строгая (но более правдоподобная) привязка, что означает что каждый фильм имеет не более одного рейтинга, вы можете упростить решения JOIN
(и избавиться от всех других запросов):
SELECT f.*
FROM film AS f
JOIN film_rating_report AS frr
ON f.filmid = frr.filmid
WHERE frr.rating = 'GE' ;
Предпочтительным решением для этого является использование join
и не забывайте group by
, чтобы у вас не было повторяющихся строк:
select film.*
from film
join film_rating_report on film.filmid = film_rating_report.filmid
and rating = 'GE'
group by film.filmid
EDIT: как правильно отметили @ypercube, я ошибался, утверждая, что производительность соединения и группы лучше, чем использование подзапросов с exists
или in
- совсем наоборот.
Query:
SELECT t1.*
FROM film t1
WHERE EXISTS (SELECT filmid
FROM film_rating_report t2
WHERE t2.rating = 'GE'
AND t2.filmid = t1.id);
Я считаю, что это сработает, подумал, не зная вашу структуру БД (подумайте о том, чтобы дать SHOW CREATE TABLE на ваших таблицах), я не знаю точно:
SELECT film.*
FROM (film)
LEFT JOIN film_rating_report ON film.filmid = film_rating_report.filmid AND film_rating_report.rating = 'GE'
WHERE film_rating_report.filmid IS NOT NULL
GROUP BY film.filmid
( WHERE film_rating_report.filmid НЕ ЯВЛЯЕТСЯ NULL, чтобы предотвратить линии, у которых нет рейтинга, который вы ищете от кражи, я добавил GROUP BY в конце, потому что film_rating_report может совпадать более одного раза - не уверен, поскольку у меня есть видимость хранящихся в нем данных)