Кто-нибудь может показать мне, почему мой SQL-запрос не работает (см. Подробности)?
-
22-08-2019 - |
Вопрос
Я использовал следующий запрос, чтобы найти дубликаты:
SELECT userID,
COUNT(userID) AS NumOccurrences
FROM userDepartments
GROUP BY userID
HAVING ( COUNT(userID) > 1 )
Затем я попытался добавить внутреннее объединение, чтобы я мог видеть совпадающие имена пользователей, которые хранятся в другой таблице.
SELECT userDepartments.userID, users.firstname, users.lastname,
COUNT(userID) AS NumOccurrences
FROM userDepartments INNER JOIN users ON userDepartments.userID = users.userID
GROUP BY userID
HAVING ( COUNT(userID) > 1 )
Но это выдало мне сообщение об ошибке, в котором говорилось, что users.firstname не был частью какой-то агрегатной функции или чего-то в этом роде...
Кто-нибудь знает, как я могу получить количество, показать только пользователей с более чем 1 отделом, а также получить имя и фамилию из другой таблицы, чтобы я мог получить список имен пользователей, которым назначено более одного отдела?
Редактировать:ЭТО ЗАПРОС, КОТОРЫЙ В КОНЕЧНОМ ИТОГЕ СРАБОТАЛ У МЕНЯ...
SELECT firstname, lastname
FROM tbl_users
WHERE (userID IN
(SELECT userID
FROM tbl_usersDepts
GROUP BY userID
HAVING (COUNT(userID) > 1)))
Решение
Я бы немного изменил запрос....
SELECT
duplicates.NumOccurrences,
duplicates.userID,
users.firstname,
users.lastname
FROM (
SELECT
userID,
COUNT(userID) AS NumOccurrences
FROM userDepartments
GROUP BY userID
HAVING COUNT(userID) > 1
) duplicates
INNER JOIN users ON duplicates.userID = users.userID
Другие советы
Движок SQL не знает, что у вас есть только одно имя пользователя для каждого идентификатора пользователя, поэтому вам нужно сгруппировать по имени и фамилии, а также по идентификатору пользователя.
SELECT userDepartments.userID, users.firstname, users.lastname,
COUNT(userID) AS NumOccurrences
FROM userDepartments INNER JOIN users ON userDepartments.userID = users.userID
GROUP BY userID, users.firstname, users.lastname
HAVING ( COUNT(userID) > 1 )
Если вы не группируете по имени и фамилии, движок не знает, что он должен делать, если он получает более одного значения firstname для данного идентификатора пользователя.Указывая ему группировать по всем трем значениям, он знает, что если для каждого идентификатора пользователя имеется более одной строки, он должен вернуть все эти строки.Даже при том, что этого не должно было произойти, движок в данном случае недостаточно умен, чтобы решить это самостоятельно.
Вы также могли бы сделать это таким образом:
SELECT users.userId, users.firstname, users.lastname, departments.NumOccurrences
FROM users INNER JOIN (
SELECT userId, count(userId) as NumOccurrences
FROM userDepartments
GROUP BY userID
HAVING ( COUNT(userID) > 1 )
) departments ON departments.userID = users.userID
Сгруппироваться по всем трем:userDepartments.Идентификатор пользователя, users.firstname и users.lastname
Вам необходимо включить user.firstname и users.lastname в ваше предложение GROUP BY - поскольку они не являются совокупными значениями (обратите внимание, что MySQL действительно поддерживает синтаксис, который вы использовали в своем запросе, но он не является стандартным).
Если вы выполняете "группировку по", то все в части "выбрать" либо должно быть:
Упомянуто в предложении "группировать по" или
Результат выполнения агрегатной функции (например, count())
Я бы сделал это таким образом (в Oracle, на всякий случай, если это не сработает в вашей системе):
SELECT users.userID, users.firstname, users.lastname, NumOccurrences
FROM users
INNER JOIN (
SELECT userID, COUNT(userID) AS NumOccurrences
FROM userDepartments
GROUP BY userID
HAVING ( COUNT(userID) > 1 )
) d
ON d.userID = users.userID
Добавьте вашего пользователя.Firstname и User.lastname в ваше предложение group by
Я вижу много хороших заметок о добавлении полей вашего имени в группу by.Хотя я думаю, что сделал бы это вот так:
SELECT Users.*, dups.NumOccurances, ud.DepartmentName
FROM Users
INNER JOIN
(
SELECT userID, COUNT(userID) AS NumOccurrences
FROM userDepartments
GROUP BY userID
HAVING ( COUNT(userID) > 1 )
) dups ON dups.userID = Users.UserID
INNER JOIN userDepartments ud ON ud.UserID=Users.UserID
ORDER BY Users.LastName, Users.FirstName, Users.UserID
Одна из причин такого подхода заключается в том, что с его помощью легче вернуться назад и получить любую другую информацию, которая вам может понадобиться.