Присоединяйтесь ко многим и объединяйте множество ссылок в одну строку

Я консультировался с подобными вопросами, но вопрос отличается, поскольку я присоединяюсь не только ко многим, но и к одному.

Пользователь

+----+-------+---------------+
| id | first | department_id |
+----+-------+---------------+
|  1 | John  | 1             |
|  2 | Jane  | 2             |
+----+-------+---------------+

отделение

+----+------------+
| id |   name     |
+----+------------+
|  1 | purchasing |
|  2 | HR         |
|  3 | marketing  |
+----+------------+

роль

+----+----------+
| id |   name   |
+----+----------+
|  1 | admin    |
|  2 | accounts |
|  3 | sales    |
+----+----------+

user_role

+--------+----------+
| user_id | role_id |
+--------+----------+
|      1  |       1 |
|      1  |       2 |
|      1  |       3 |
|      2  |       2 |
|      2  |       3 |
+--------+----------+

SQL

SELECT user.first, GROUP_CONCAT(role.name), department.id AS 'department.id', department.name AS 'department.name'
FROM user 
INNER JOIN department ON user.department_id
INNER JOIN user_role ON user.id = user_role.user_id
INNER JOIN role ON user_role.role_id = role.id
GROUP BY user.name;

Ожидание

John, "admin,accounts,sales", 1, purchasing
Jane, "accounts,sales", 2, HR

По сути, это объединение 4 таблиц: многие ко многим и 1 ко многим с функцией группового объединения.

запрос выдает ошибку.

Error Code: 1055. Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'department.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

Что ваш запрос дает в качестве вывода?

Barbaros Özhan 27.05.2019 20:13

У меня ошибка, посмотрите мое редактирование, пожалуйста

AppDeveloper 27.05.2019 20:17
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
2
41
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поскольку отдел уникален для каждого пользователя, вы можете использовать max(), чтобы получить сведения об отделе, чтобы преодолеть ограничения, налагаемые group by.

SELECT 
  user.first, 
  GROUP_CONCAT(role.name) AS roles, 
  max(department.id) AS department_id, 
  max(department.name) AS department_name
FROM user 
INNER JOIN department ON user.department_id = department.id
INNER JOIN user_role ON user.id = user_role.user_id
INNER JOIN role ON user_role.role_id = role.id
GROUP BY user.first;

Также, если имя пользователя не уникально, вам следует:

GROUP BY user.id, user.first

Также псевдонимы столбцов не должны заключаться в одинарные кавычки. Вместо этого используйте обратные кавычки.

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

AppDeveloper 27.05.2019 20:19

Да, каждый столбец в списке выбора должен быть либо в предложении group by, либо в агрегированном виде.

forpas 27.05.2019 20:20

хорошо, а это ограничение наложено из-за использования функции GROUP_CONCAT или из-за предложения GROUP BY?

AppDeveloper 27.05.2019 20:22

Из-за группы. GROUP_CONCAT() — это агрегированный столбец. В качестве альтернативы max() вы можете использовать any_value().

forpas 27.05.2019 20:24

Я только что проверил, не используя max или any_value, и это работает, не знаю. Есть идеи

AppDeveloper 27.05.2019 20:32

MySql допускает это, когда для атрибута only_full_group_by установлено значение false, но ошибка, которую вы упоминаете в вопросе, означает, что для него установлено значение true.

forpas 27.05.2019 20:34

Что делает MySql, так это выбирает значение для столбца (любое значение), но в вашем случае есть только 1 значение, поэтому результат правильный. В других rdbms, таких как sqlserver, это было бы запрещено.

forpas 27.05.2019 20:36

Вы можете найти больше здесь: dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

forpas 27.05.2019 20:37

я думаю, потому что у меня не было user.id в моем select и group by, поэтому это выдавало ошибку.

AppDeveloper 27.05.2019 20:40

хорошо, я буду использовать any_value, чтобы быть в безопасности, надеюсь, any_value поддерживается и на сервере mysql, в противном случае я буду использовать max, потому что у меня будет вариант использования, чтобы это было кросс-платформенное решение db

AppDeveloper 27.05.2019 20:41

Поскольку user.id не был включен ни в группу, ни в выборку, проблем нет. Но на всякий случай используйте user.id в группе, если имена пользователей не уникальны. Также ошибка может быть вызвана тем, что вы заключили псевдоним «department.id» в одинарные кавычки вместо обратных или квадратных скобок.

forpas 27.05.2019 20:44

хорошо, исправлено, теперь используются обратные кавычки, однако вы имеете в виду квадратную скобку [department.id] ? мне выдало ошибку

AppDeveloper 27.05.2019 20:50

Правильно, для mysql вы должны использовать обратные кавычки. Квадратные скобки работают на сервере sql и sqlite.

forpas 27.05.2019 20:51

ну, я думаю, что мне нужно управлять двумя сценариями sql, из-за обратных кавычек и квадратных скобок, здесь одинарная кавычка работала в mysql, если она работает на сервере sql, то у меня есть кросс-платформенный сценарий, в противном случае :( Я очень ценю ваша помощь.

AppDeveloper 27.05.2019 20:56

Если вы планируете перенести код на сервер sql, то вы должен используете max() (там нет any_value()).

forpas 27.05.2019 20:57

конечно, я сейчас на месте

AppDeveloper 27.05.2019 20:59

Другие вопросы по теме