Это мой скрипт SQL : скрипт SQL
Я пытаюсь повторить этот результат с помощью PHP. Это мой ожидаемый результат:
// Some Stuff Here The Dark Knight Rises - 7.5 Batman Begins - 7.5 Iron Man - 7.3 The Lord of the Rings: The Return of the King - 8.1 etc... // Some more Stuff here
Мой PHP-код:
$stmt = $conn->prepare("SELECT tmdb_movies.movie_title ,GROUP_CONCAT(recommendations.recommendations_title ORDER BY recommendations.recommendations_title) as recommendations_title ,GROUP_CONCAT(recommendations.recommendations_vote_average ORDER BY recommendations.recommendations_title) as recommendations_vote_average FROM tmdb_movies LEFT JOIN cast ON cast.cast_tmdb_id=tmdb_movies.tmdb_id LEFT JOIN recommendations ON recommendations.recommendations_tmdb_id=tmdb_movies.tmdb_id Where tmdb_movies.tmdb_id= 155 GROUP BY tmdb_movies.movie_title "); // Then fire it up $stmt->execute(); // Pick up the result as an array $result = $stmt->fetchAll(); // Now you run through this array in many ways, for example for($x=0, $n=count($result); $x < $n; $x++){ $recommendations_name_list = explode(',',$result[$x]["recommendations_title"]); $recommendations_vote_average = explode(',',$result[$x]["recommendations_vote_average"]); foreach( $recommendations_name_list as $index => $recommendations_title ) { echo' <p>'.$recommendations_title.'- '.$recommendations_vote_average[$index].'</p>'; } }
Batman Begins- 7.5 Batman Begins- 7.5 Batman Begins- 7.5 Batman Begins- 7.5 Batman Begins- 7.5 Batman Begins- 7.5 Batman Begins- 7.5 Batman Begins- 7.5 Batman Begins- 7.5 Batman Begins- 7.5 Captain America: The First Avenger- 6.6 Captain America: The First Avenger- 6.6 Captain America: The First Avenger- 6.6 Captain America: The First Avenger- 6.6 Captain America: The First Avenger- 6.6 Captain America: The First Avenger- 6.6 Captain America: The First Avenger- 6.6 Captain America: The First Avenger- 6.6 Captain America: The First Avenger- 6.6 Captain America: The First Avenger- 6.6 Inception- 8 Inception- 8 Inception- 8 Inception- 8 Inception- 8 Inception- 8 Inception- 8 Inception- 8 Inception- 8 Inception- 8 Iron Man- 7.3 Iron Man- 7.3 Iron Man- 7.3 Iron Man- 7.3 Iron Man- 7.3 Iron Man- 7.3 Iron Man- 7.3 Iron Man- 7.3 Iron Man- 7.3 Iron Man- 7.3 Iron Man 2- 6.6 Iron Man 2- 6.6 Iron Man 2- 6.6 Iron Man 2- 6.6 Iron Man 2- 6.6 Iron Man 2- 6.6 Iron Man 2- 6.6 Iron Man 2- 6.6 Iron Man 2- 6.6 Iron Man 2- 6.6 The Dark Knight Rises- 7.5 The Dark Knight Rises- 7.5 The Dark Knight Rises- 7.5 The Dark Knight Rises- 7.5 The Dark Knight Rises- 7.5 The Dark Knight Rises- 7.5 The Dark Knight Rises- 7.5 The Dark Knight Rises- 7.5 The Dark Knight Rises- 7.5 The Dark Knight Rises- 7.5 The Lord of th- 8
Но если я удалю эту строку LEFT JOIN cast ON cast.cast_tmdb_id=tmdb_movies.tmdb_id
тогда мой PHP-код работает нормально.
Ожидаемый результат:
Batman Begins- 7.5 Captain America: The First Avenger- 6.6 Inception- 8 Iron Man- 7.3 Iron Man 2- 6.6 The Dark Knight Rises- 7.5 The Lord of the Rings: The Fellowship of the Ring- 8 The Lord of the Rings: The Return of the King- 8.1 The Lord of the Rings: The Two Towers- 7.9 The Matrix- 7.9
Использование приведения в действие LEFT JOIN cast
нецелесообразно для значений выбора (результаты выбираются как ayway, потому что они основаны на maun table movie_title и не возвращают полезную информацию, потому что в таблице выбора нет столбцов из таблицы di) и производят результирующий набор с большим количеством строк
поэтому, если вы хотите настаивать на левом соединении, вы можете добавить DISTINCT к вашему исходному запросу
SELECT DISTICNT tmdb_movies.movie_title ,GROUP_CONCAT(recommendations.recommendations_title ORDER BY recommendations.recommendations_title) as recommendations_title ,GROUP_CONCAT(recommendations.recommendations_vote_average ORDER BY recommendations.recommendations_title) as recommendations_vote_average FROM tmdb_movies LEFT JOIN cast ON cast.cast_tmdb_id=tmdb_movies.tmdb_id LEFT JOIN recommendations ON recommendations.recommendations_tmdb_id=tmdb_movies.tmdb_id Where tmdb_movies.tmdb_id= 155 GROUP BY tmdb_movies.movie_title
или лучше не использовать левое соединение pn cast
SELECT tmdb_movies.movie_title ,GROUP_CONCAT(recommendations.recommendations_title ORDER BY recommendations.recommendations_title) as recommendations_title ,GROUP_CONCAT(recommendations.recommendations_vote_average ORDER BY recommendations.recommendations_title) as recommendations_vote_average FROM tmdb_movies LEFT JOIN recommendations ON recommendations.recommendations_tmdb_id=tmdb_movies.tmdb_id Where tmdb_movies.tmdb_id= 155 GROUP BY tmdb_movies.movie_title
Многие из вещей, которые у вас есть в вашем посте, не складываются. В вашем скрипте sql отсутствует таблица отливок. Я уже прокомментировал, что вы используете GROUP_CONCAT неадекватно. У вашего вопроса нет полной информации, чтобы помочь нам понять вашу проблему.
С учетом сказанного, я считаю, что я предположил нечто близкое к тому, что вы на самом деле хотите. Основная проблема заключается в том, что ваша GROUP BY должна включать как оригинальный фильм, так и рекомендуемые фильмы. Это вернет вам одну строку за групповую комбинацию фильма / рекомендации. Вы можете использовать GROUP_CONCAT, чтобы получить бросок в одном столбце. Кроме того, я считаю, что данные роли, которые вы хотите, на самом деле являются отличным от рекомендуемого фильма, а не для оригинального фильма. Вы могли бы получить оба вместе, но в контексте этого запроса мне кажется, что вы хотите, чтобы бросок рекомендуемого фильма собрался в один столбец с GROUP_CONCAT. Как я вам прокомментировал, проблема в том, что в таблице рекомендаций у вас нет tmdb_id рекомендуемого фильма. Совершенно откровенно, что это денормализованная структура (хранящая заголовок, а не идентификатор), и является реляционно неверной, расточительной и потенциально запутанной.
Почему это?
Во-первых, в таблице рекомендаций нет основного ключа, и он нуждается в нем. Название тоже не является хорошим кандидатом, потому что есть много фильмов, имеющих один и тот же титул. С вашей системой нет способа определить, какой фильм из нескольких, которые могут иметь одинаковое название. Таким образом, то, что вы должны иметь, это tmdb_id как внешний ключ, и в этот момент вам не нужно (или не хотеть) заголовок, потому что его можно было бы получить из таблицы tmdb_movies. Ваша таблица рекомендаций по существу является таблицей «многие ко многим», которая связывает фильмы друг с другом в родительском по отношению к ребенку. Помимо внешних ключей (tmdb_id, recommended_tmdb_id) на самом деле не должно быть ничего другого в таблице, так как значения, которые у вас в настоящее время есть (название, средний рейтинг), являются денормализованными значениями, которые хранятся в таблице tmdb_movies.
Теперь подумайте о будущем, когда, возможно, у вас есть тысячи фильмов, каждый из которых может иметь 10 рекомендуемых фильмов, связанных с ним. Вы будете тратить на один фильм, мегабайт хранилища баз данных, повторяя тот же заголовок и среднее значение, которое не изменяется. Хуже того, средние значения являются моментальными снимками. Всякий раз, когда средняя оценка должна быть пересчитана, вместо того, чтобы обновлять одно значение в одной строке таблицы tmdb_movie, теперь вам нужно обновить каждую отдельную строку в рекомендации, где этот фильм был рекомендован оригиналу. Это некоторые из затрат на де-нормализацию.
Теперь о специфике GROUPing.
Сначала, чтобы проиллюстрировать, как работает GROUP BY, я предлагаю вам запустить эти запросы в вашем sqlfiddle или live db:
SELECT tmdb_movies.movie_title, recommendations.recommendations_title, recommendations.recommendations_vote_average FROM tmdb_movies LEFT JOIN recommendations ON recommendations.recommendations_tmdb_id=tmdb_movies.tmdb_id GROUP BY tmdb_movies.tmdb_id, recommendations.recommendations_title Where tmdb_movies.tmdb_id=1
Главное, что отличается от того, что вы делали, заключается в том, что я удалил бесполезные операторы GROUP_CONCAT и сделал GROUP BY на tmdb_movies.tmdb_id, рекомендациях.recommendations_title.
В идеале это было бы по id, но я рассмотрел это выше, так что теперь нам нужно просто использовать заголовок.
Как вы можете видеть, вы получаете группу для каждой уникальной комбинации Movie & Recommended Movie. Похоже, это то, что вы хотите. Обратите внимание, что я вообще не использовал GROUP_CONCAT, и вы получаете среднее значение и заголовок, по одному в строке.
Теперь предположим, что вы хотите также присоединиться к таблице отливок.
Добавим, что в:
SELECT tmdb_movies.movie_title, recommendations.recommendations_title, recommendations.recommendations_vote_average FROM tmdb_movies LEFT JOIN recommendations ON recommendations.recommendations_tmdb_id=tmdb_movies.tmdb_id LEFT JOIN cast ON cast.recommendations_title=recommendations.recommendations_title GROUP BY tmdb_movies.tmdb_id, recommendations.recommendations_title
Обратите внимание, что НИЧЕГО НЕ ИЗМЕНЯЕТ. Вы не получаете посторонние строки, потому что GROUP BY уже уменьшает дубликаты и оставляет одну строку на группу, даже если мы теперь присоединяемся к movie-> рекомендация-> cast
Итак, теперь я предполагаю, что вы хотите, чтобы в одном столбце вы попадали в результате. Вот здесь GROUP_CONCAT действительно полезен и кажется уместным:
SELECT tmdb_movies.movie_title, recommendations.recommendations_title, recommendations.recommendations_vote_average, GROUP_CONCAT(cast.name) FROM tmdb_movies LEFT JOIN recommendations ON recommendations.recommendations_tmdb_id=tmdb_movies.tmdb_id LEFT JOIN cast ON cast.recommendations_title=recommendations.recommendations_title GROUP BY tmdb_movies.tmdb_id, recommendations.recommendations_title
Вот sqlfiddle к этому :