2017-02-03 7 views
0

Использование MySQL 5.7, у меня есть movie таблицу, которая имеет много полей единственное значение:Есть ли способ извлекать данные из множества таблиц один-ко-многим во время одного вызова с MySQL?

+--------------+--------------+ 
| Field  | Type   | 
+--------------+--------------+ 
| id   | int(11)  | 
| title  | varchar(255) | 
| release_year | int(11)  | 
| rating  | int(11)  | 
+--------------+--------------+ 

Когда я звоню запрос на этой таблице, как SELECT * FROM movie WHERE id = 5 он будет возвращать только одну строку с данными каждого столбца, как и ожидалось.

У меня есть несколько таблиц с отношением «один ко многим» с этой таблицей movie. У меня movie_subtitle, movie_language, movie_actor и т.д. Вот один, например:

+--------------+--------------+ 
| Field  | Type   | 
+--------------+--------------+ 
| id   | int(11)  | 
| movie_id  | int(11)  | 
| subtitle  | varchar(255) | 
+--------------+--------------+ 

Моя проблема заключается в том, что для того, чтобы мне получить все данные поля для одного фильма, кажется, мне нужно сделать около 10 SELECT звонков. Один для таблицы movie, а затем по одному для каждой добавочной надстройки.

Если у пользователя есть 1000 фильмов, это быстро может превратиться в 10 000 звонков SELECT, если я пытаюсь запустить большой запрос по всей коллекции.

Есть ли способ сделать все это в один позвонить? Или это так, как должно быть? Я чувствую, что есть лучший способ сделать это, и я просто недостаточно осведомлен о связях с базой данных, чтобы понять, чего я здесь не вижу.

Мне нужно передать данные, полученные из этих вызовов, на мою страницу PHP, чтобы поместить ее в JSON.

+0

Есть ли причина, по которой вы не просто используете объединения для группировки данных? Без структуры таблицы, образцы данных (возможно, sql скрипка) и зная, что вы хотите в качестве образца, люди здесь просто будут гадать. –

+0

Я бы предложил либо объединить данные вместе, либо выполнить несколько запросов, вытягивая дополнительные данные, которые вы можете объединить позже в php. В случае объединений он отлично работает, но вы, как правило, получаете дублирующиеся данные в своем возвратном результате, и вам придется игнорировать его или в зависимости от вашего вывода, вы также можете объединить данные group_concat в один столбец. С несколькими запросами он практически не выигрывает только для одной записи, но с несколькими записями количество запросов не увеличивается. –

+0

'JOIN' возвращает много строк с теми же данными, за исключением одного столбца ... например: Фильм Goonies вернет три строки, все с одинаковыми данными, ожидайте, что столбец' genre' в каждой строке будет Adventure , Комедия и Семья. Просто ищем способ избежать этого. –

ответ

0

Я бы предложил делать несколько запросов и коалесцировать данные в php. Вот простой пример для фильмов и жанров:

Примеры таблиц:

Table: MOVIES 
    id, title, release_year, rating ...etc 

Table: MOVIES_GENRES (many-to-many relation to movies and genres) 
    movie_id, genre_id 

Table: GENRES 
    id, name, description 

Table: USERS_MOVIES (many-to-many relation to users and movies) 
    user_id, movie_id 

Затем вы можете сделать что-то вроде этого:

//example user id 
$user_id = 5; 

//query for all movies 
$sql = "SELECT * FROM `movies` WHERE `id` IN (SELECT `movie_id` FROM `users_movies` WHERE `user_id`={$user_id})"; 

$result = /*perform query*/; 

//loop over the result 
$movies = array(); 
while($row = $result->fetch(PDO::FETCH_ASSOC)){ 
    //add the row to the movies array with the movie id as the key 
    $movies[$row['ID']] = $row; 

    //also add an empty genre array in anticipation of genre data being coalesced 
    $movies['genres'] = array(); 
} 

//get a comma separated list of all the movie ids for use in queries below 
$movieIDs = implode(',', array_keys($movies)); 

//now query out genre based on movies, make sure to get the movie_id for coalesce 
$sql = "SELECT `movie_id`, `name`, `description` FROM `genres` JOIN `movies_genres` ON `genre_id`=`genres`.`id` WHERE `movie_id` IN ({$movieIDs})"; 

$result = /*perform query*/; 

//loop over the result 
while($row = $result->fetch(PDO::FETCH_ASSOC)){ 
    //add the genre to this movie 
    $movies[$row['movie_id']]['genres'][] = $row; 
} 

В этом все дело, я использую только два запроса, независимо сколько фильмов. Я просто создаю список всех идентификаторов фильмов и использую их в последующих запросах. Затем объедините данные обратно в php. Позже по линии я могу перебрать массив $movies и использовать его для построения таблицы или того, что мне нужно. В запросе жанра вы также можете включить соединение (или подзапрос) в users_movies на movie_id, а затем не нужно большой список IN, но он может использовать user_id сверху.