Этот запрос MySQL JOIN, обычный запрос или оба?

0

Мне нужно получить данные из трех разных таблиц. Я знаю основы JOINs, но когда дело доходит до более сложных запросов, таких как получение данных из трех или более таблиц с помощью JOIN, я немного запутался, и я просто начинаю играть с запросами, пишущими, что имеет смысл для меня, как и следующий:

SELECT movies.imdbID,
  movies.title,
  movies.year,
  movie_ratings.votes,
  movie_ratings.total_value,
  movie_ratings_external.votes,
  movie_ratings_external.total_value
FROM movies, movie_ratings_external
LEFT JOIN movie_ratings ON movie_ratings.imdbID = movie_ratings_external.imdbID
WHERE movies.imdbID = movie_ratings_external.imdbID
ORDER BY movie_ratings.votes DESC, movie_ratings_external.votes DESC
LIMIT 30

Этот запрос работает. Я получаю выбранные поля из правильных таблиц и упорядочиваю правильный путь, но я думаю, что я смешиваю вещи (например, обычные запросы к двум таблицам и JOINING между двумя таблицами), и я уверен, что это лучший/более эффективный способ выполнения ту же самую пурпуру.

Доступен какой-нибудь DB geek?

Теги:
performance

4 ответа

1
Лучший ответ

Изменен ваш запрос чуть-чуть. Все остальное было довольно много.

Я не совсем уверен, что вы называете "регулярным запросом", но Joins - это почти основная часть обычного запроса.

В вашем старом запросе эта часть FROM movies, movie_ratings_external была в основном CROSS JOIN. Заменил его на JOIN (я использовал a LEFT JOIN, полагая, что вы всегда хотели вернуть все фильмы, но основное намерение состояло в том, что CROSS JOIN с фильтрацией в WHERE является намного более неэффективным, потому что вы манипулируете больше ROWS - особенно ненужные)

Подумайте об этом так. Каждый оператор Join в вашем SELECT возвращает набор строк, которые затем присоединяются к следующей таблице в JOIN. Идея должна состоять в том, чтобы последовательно пробовать строки фильтра с каждым объединением, насколько это возможно, чтобы вы не получали ненужные кортежи. То, где появляются утверждения ON.

Удалено

SELECT 
  movies.imdbID,
  movies.title,
  movies.year,
  movie_ratings.votes,
  movie_ratings.total_value,
  movie_ratings_external.votes,
  movie_ratings_external.total_value
FROM movies 
LEFT OUTER JOIN movie_ratings_external
     ON movies.imdbID = movie_ratings_external.imdbID
LEFT JOIN movie_ratings 
     ON movie_ratings.imdbID = movie_ratings_external.imdbID
ORDER BY movie_ratings.votes DESC, movie_ratings_external.votes DESC
LIMIT 30

Надеюсь, что это поможет!

1

Вы делаете 2 соединения. Однако вы смешиваете свои синтаксисы, что снижает читаемость.

Либо сделайте

SELECT movies.imdbID,
  movies.title,
  movies.year,
  movie_ratings.votes,
  movie_ratings.total_value,
  movie_ratings_external.votes,
  movie_ratings_external.total_value
FROM movies
LEFT JOIN movie_ratings_external ON movies.imdbID = movie_ratings_external.imdbID
LEFT JOIN movie_ratings ON movie_ratings.imdbID = movie_ratings_external.imdbID
ORDER BY movie_ratings.votes DESC, movie_ratings_external.votes DESC
LIMIT 30

или как это

SELECT movies.imdbID,
  movies.title,
  movies.year,
  movie_ratings.votes,
  movie_ratings.total_value,
  movie_ratings_external.votes,
  movie_ratings_external.total_value
FROM movies, movie_ratings_external, movie_ratings 
WHERE movies.imdbID = movie_ratings_external.imdbID
  AND movie_ratings.imdbID = movie_ratings_external.imdbID
ORDER BY movie_ratings.votes DESC, movie_ratings_external.votes DESC
LIMIT 30

Я также не уверен, почему вы остались. Если рейтинг может не существовать для определенного фильма, который вы хотите присоединиться к таблице фильмов.

Если это ваше намерение, ваш запрос должен выглядеть так.

SELECT movies.imdbID,
  movies.title,
  movies.year,
  movie_ratings.votes,
  movie_ratings.total_value,
  movie_ratings_external.votes,
  movie_ratings_external.total_value
FROM movies
LEFT OUTER JOIN movie_ratings_external ON movies.imdbID = movie_ratings_external.imdbID
LEFT OUTER JOIN movie_ratings ON movies.imdbID = movie_ratings.imdbID
ORDER BY movie_ratings.votes DESC, movie_ratings_external.votes DESC
LIMIT 30
0

В запросе ничего плохого. Но я предпочитаю что-то вроде следующего - ради удобочитаемости:

SELECT  Movie.imdbID 
,       Movie.title 
,       Movie.year 
,       Rating.votes 
,       Rating.total_value 
,       ExternalRating.votes 
,       ExternalRating.total_value 

FROM    movies Movie 
    LEFT JOIN
        movie_ratings_external ExternalRating

 ON     Movie.imdbID = ExternalRating.imdbID 

    LEFT JOIN movie_ratings Rating

ON      Rating.imdbID = ExternalRating.imdbID 

ORDER   BY 
        Rating.votes DESC
,       ExternalRating.votes DESC 
0

Первый синтаксис, который вы используете

FROM tableA, tableB
WHERE tableA.abc = tableB.def

является еще одним синтаксисом для регулярного внутреннего соединения и, действительно, единственным синтаксисом, который вы можете использовать на некоторых СУБД, таких как Informix - эти два должны быть полностью эквивалентными. Я думаю, что сбивать с толку и сопоставлять синтаксисы, поэтому я бы выбрал один и придерживался его. Настоящим тестом было бы проверить план запросов mysql до и после переключения, но я был бы очень удивлен, если бы он вообще менял.

Эффективность: пока у вас есть индексы во всех правильных столбцах, т.е. столбец imdbID во всех трех таблицах, я не вижу ничего, что вы можете сделать, чтобы улучшить это. Я не думаю, что вам нужен индекс в столбцах, которые вы заказываете, но это может стоить проверить, если вы ищете улучшения.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню