#mysql #many-to-many #pivot
#mysql #»многие ко многим» #pivot
Вопрос:
В настоящее время у меня есть две таблицы, похожие на users
и programs
, которые связаны через отношения «многие ко многим» посредством link
таблицы.
mysql> select * from users;
---- ----------
| id | name |
---- ----------
| 1 | Jonathan |
| 2 | Little |
| 3 | Annie |
| 4 | Bob |
---- ----------
4 rows in set (0.00 sec)
mysql> select * from programs;
---- ----------------------
| id | name |
---- ----------------------
| 1 | Microsoft Word |
| 2 | Microsoft Excel |
| 3 | Microsoft PowerPoint |
---- ----------------------
3 rows in set (0.00 sec)
mysql> select * from link;
--------- ------------
| user_id | program_id |
--------- ------------
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 2 |
| 3 | 1 |
| 3 | 4 |
--------- ------------
6 rows in set (0.00 sec)
Я понимаю, как объединять таблицы и возвращать результат такого рода:
mysql> select users.name, programs.name from linker
-> join users on users.id = linker.user_id
-> join programs on programs.id = linker.program_id;
---------- ----------------------
| name | name |
---------- ----------------------
| Jonathan | Microsoft Word |
| Jonathan | Microsoft Excel |
| Jonathan | Microsoft PowerPoint |
| Little | Microsoft Excel |
| Annie | Microsoft Word |
---------- ----------------------
Но то, что я действительно ищу, немного сложнее:
---------- -----------------------------------------------------
| name | name |
---------- -----------------------------------------------------
| Jonathan | Microsoft Word,Microsoft Excel,Microsoft PowerPoint |
| Little | Microsoft Excel |
| Annie | Microsoft Word |
---------- -----------------------------------------------------
Я предполагаю, что где-то в команде есть GROUP_CONCAT()
, но, похоже, я не могу заставить результаты выглядеть так:
mysql> select users.name, group_concat(programs.name) from linker
-> join users on users.id = linker.user_id
-> join programs on programs.id = linker.program_id;
---------- ------------------------------------------------------------------------------------
| name | group_concat(programs.name) |
---------- ------------------------------------------------------------------------------------
| Jonathan | Microsoft Word,Microsoft Excel,Microsoft PowerPoint,Microsoft Excel,Microsoft Word |
---------- ------------------------------------------------------------------------------------
Кто-нибудь может указать мне правильное направление?
Ответ №1:
Вам нужно указать DISTINCT
, т.е.
select users.name, group_concat( DISTINCT programs.name)
Смотрите документы MySQL здесь.
Попробуйте изменить свой запрос на:
SELECT users.name, group_concat(programs.name)
from users
LEFT JOIN linker on linker.user_id = users.id
LEFT JOIN programs on linker.program_id = programs.id
GROUP BY users.id
Это даст вам null
для любого пользователя, с которым не связаны программы. Чтобы отфильтровать их, просто добавьте WHERE programs.id IS NOT NULL
.
Комментарии:
1. Это устраняет повторяющиеся значения, но также ограничивает результаты первой строкой.
2. Обновлен ответ — попробуйте запрос выше.
3. Ах, это было
GROUP BY
предложение, которое я пропустил. Большое вам спасибо!
Ответ №2:
SELECT users.name, group_concat(programs.name) from linker
INNER JOIN users on linker.user_id = users.id
INNER JOIN programs on linker.program_id = programs.id
GROUP BY users.id;
Комментарии:
1. Это по-прежнему возвращает только первую строку, включая дополнительные (повторяющиеся) имена программ. Я думаю, что тест на равенство вычисляется одинаково независимо от порядка.
2. @kpsfire аааа! да, вы правы, моя ошибка, порядок важен, когда вы используете левое или правое объединение.