Я использую Mysql, так как довольно долгое время и действительно смущен результатом простой LEFT JOIN на трех таблицах.Mysql LEFT JOIN из трех таблиц возвращается ко многим строкам
я следующие три таблицы (я создал пример, чтобы сузить)
а) человек
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| PersonID | int(11) | NO | PRI | NULL | auto_increment |
| Name | varchar(50) | YES | | NULL | |
| Age | int(11) | YES | | NULL | |
+----------+-------------+------+-----+---------+----------------+
б) person_fav_artists
+----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+----------------+
| FavInterpretID | int(10) | NO | PRI | NULL | auto_increment |
| PersonID | int(10) | NO | | 0 | |
| Interpret | varchar(100) | YES | | NULL | |
+----------------+--------------+------+-----+---------+----------------+
гр) person_fav_movies
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| FavMovieID | int(10) | NO | PRI | NULL | auto_increment |
| PersonID | int(10) | NO | | 0 | |
| Movie | varchar(100) | YES | | NULL | |
+------------+--------------+------+-----+---------+----------------+
Мои таблицы примеров используются для хранения любого количества художников и фильмов для одного человека. Погодные условия это не имеет значения, так как это просто простой пример.
Теперь у меня есть следующие данные в таблицах:
mysql> SELECT * FROM persons;
+----------+------+------+
| PersonID | Name | Age |
+----------+------+------+
| 1 | Jeff | 22 |
| 2 | Lisa | 15 |
| 3 | Jon | 30 |
+----------+------+------+
mysql> SELECT * FROM person_fav_artists;
+----------------+----------+----------------+
| FavInterpretID | PersonID | Interpret |
+----------------+----------+----------------+
| 1 | 1 | Linkin Park |
| 2 | 1 | Muse |
| 3 | 2 | Madonna |
| 4 | 2 | Katy Perry |
| 5 | 2 | Britney Spears |
| 6 | 1 | Fort Minor |
| 7 | 1 | Jay Z |
+----------------+----------+----------------+
mysql> SELECT * FROM person_fav_movies;
+------------+----------+-------------------+
| FavMovieID | PersonID | Movie |
+------------+----------+-------------------+
| 1 | 1 | American Pie 1 |
| 2 | 1 | American Pie 2 |
| 3 | 1 | American Pie 3 |
| 4 | 3 | A Game of Thrones |
| 5 | 3 | Eragon |
+------------+----------+-------------------+
Теперь i'm просто соединения таблиц с помощью следующего запроса:
Select * FROM persons
LEFT JOIN person_fav_artists USING (PersonID)
LEFT JOIN person_fav_movies USING (PersonID);
, который возвращает следующий результат:
+----------+------+------+----------------+----------------+------------+-------------------+
| PersonID | Name | Age | FavInterpretID | Interpret | FavMovieID | Movie |
+----------+------+------+----------------+----------------+------------+-------------------+
| 1 | Jeff | 22 | 1 | Linkin Park | 1 | American Pie 1 |
| 1 | Jeff | 22 | 1 | Linkin Park | 2 | American Pie 2 |
| 1 | Jeff | 22 | 1 | Linkin Park | 3 | American Pie 3 |
| 1 | Jeff | 22 | 2 | Muse | 1 | American Pie 1 |
| 1 | Jeff | 22 | 2 | Muse | 2 | American Pie 2 |
| 1 | Jeff | 22 | 2 | Muse | 3 | American Pie 3 |
| 1 | Jeff | 22 | 6 | Fort Minor | 1 | American Pie 1 |
| 1 | Jeff | 22 | 6 | Fort Minor | 2 | American Pie 2 |
| 1 | Jeff | 22 | 6 | Fort Minor | 3 | American Pie 3 |
| 1 | Jeff | 22 | 7 | Jay Z | 1 | American Pie 1 |
| 1 | Jeff | 22 | 7 | Jay Z | 2 | American Pie 2 |
| 1 | Jeff | 22 | 7 | Jay Z | 3 | American Pie 3 |
| 2 | Lisa | 15 | 3 | Madonna | NULL | NULL |
| 2 | Lisa | 15 | 4 | Katy Perry | NULL | NULL |
| 2 | Lisa | 15 | 5 | Britney Spears | NULL | NULL |
| 3 | Jon | 30 | NULL | NULL | 4 | A Game of Thrones |
| 3 | Jon | 30 | NULL | NULL | 5 | Eragon |
+----------+------+------+----------------+----------------+------------+-------------------+
17 rows in set (0.00 sec)
Пока все хорошо. Мой вопрос теперь, если он «нормальный», что «12» Строки возвращаются для человека «Джефф», несмотря на то, что у него только четыре «артиста» и три «фильма», назначенные ему. Я думаю, что могу понять, почему результат такой, какой есть, но я думаю, что очень глупо возвращать так много строк для столь менее реальных данных.
Так что с моим запросом что-то не так, или это намерение?
Результат Я бы хотел, чтобы было бы, как следующие (только для Джеффа):
+----------+------+------+----------------+----------------+------------+-------------------+
| PersonID | Name | Age | FavInterpretID | Interpret | FavMovieID | Movie |
+----------+------+------+----------------+----------------+------------+-------------------+
| 1 | Jeff | 22 | 1 | Linkin Park | 1 | American Pie 1 |
| 1 | Jeff | 22 | 2 | Muse | 2 | American Pie 2 |
| 1 | Jeff | 22 | 3 | Fort Minor | 3 | American Pie 3 |
| 1 | Jeff | 22 | 4 | Jay Z | 1 | NULL | <- 'American Pie 1/2/3' would be OK as well.
+----------+------+------+----------------+----------------+------------+-------------------+
Спасибо за вашу помощь!
Спасибо за ваш ответ! Я уже понимаю, что это «правильный» результат, поскольку он возвращает все возможные комбинации. О твоем вопрос: Я присоединяюсь к таблицам, чтобы создать объект «Человек» на C#, который имеет списки, содержащие «Фильмы» и «Художники». Я использую этот запрос для создания всего объекта, поэтому я соединяю все вместе. Возможно, было бы разумнее сделать это отдельно, но тогда у меня будет намного больше запросов ... – user1288392
Если вы используете объект C#, который имеет возможность «фильтровать» записи, вы, конечно, можете использовать фильтр данные и применить это к вашему объекту/представлению, а затем повторно фильтровать и применять его к другому объекту/представлению. Это заставило бы ваш SQL тянуть одно нажатие, хотя я бы предложил не. Время, затрачиваемое на объединение данных из третьей таблицы, будет таким же, как и для второго оператора, потому что ваша первая таблица кэшируется. –
Да, вы правы, мой объект типа C# «фильтрует» результат из Mysql-Query. Это означает, что дублированные строки просто игнорируются. Я не понимаю, что я понял вторую часть вашего ответа. Вы имеете в виду, что я должен использовать больше запросов вместо одного большого, как я сделал в моем примере? Это означало бы, что я должен создать отдельный запрос для фильмов и один для художников. – user1288392