¿Alguien puede demostrar por qué mi consulta SQL no está funcionando (ver detalles)?
-
22-08-2019 - |
Pregunta
He utilizado la siguiente consulta para encontrar duplicados:
SELECT userID,
COUNT(userID) AS NumOccurrences
FROM userDepartments
GROUP BY userID
HAVING ( COUNT(userID) > 1 )
Luego trató añadiendo una combinación interna para que pudiera ver los nombres de usuarios que correspondan, que se almacenan en una tabla diferente.
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 )
Pero me dio un error diciendo que users.firstname no era parte de una función agregada o algo ...
¿Alguien sabe cómo puedo obtener el recuento, sólo mostrar a los usuarios con más de 1 departamento, y también obtener el nombre y apellido de la otra tabla para que pueda obtener una lista de los nombres de los usuarios que tienen más de un departamento asignado?
EDITAR: Esta es la consulta que terminó trabajando para mí ...
SELECT firstname, lastname
FROM tbl_users
WHERE (userID IN
(SELECT userID
FROM tbl_usersDepts
GROUP BY userID
HAVING (COUNT(userID) > 1)))
Solución
Me reorganizar la consulta un poco ....
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
Otros consejos
El motor de SQL no sabe que sólo tiene un nombre de usuario por ID de usuario, así que hay que agrupar por nombre y apellido, así como por la identificación del usuario.
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 )
Si no lo hace por el grupo nombre y apellido, el motor no se sabe lo que tiene que hacer si se pone más de un valor de Nombre de un id de usuario dado. Al decirle que al grupo por los tres valores, se sabe que si hay más de una fila por cada ID de usuario, se debe devolver todas las filas. A pesar de que esto no debería ocurrir, el motor no es lo suficientemente inteligente como en este caso para decidir que por su propia cuenta.
También puede hacerlo de esta manera:
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
Grupo de los tres: el userDepartments.userID, users.firstname y users.lastname
Es necesario incluir user.firstname y users.lastname en su cláusula GROUP BY - ya que no son valores agregados (tenga en cuenta que MySQL no soporta realmente la sintaxis que se ha utilizado en la consulta, pero no es estándar).
Si lo hace un "grupo por" entonces todo en la parte de "seleccionar" o bien tiene que ser:
-
mencionado en el "grupo por" cláusula o
-
El resultado de una función de agregado (como count ())
Me gustaría hacerlo de esta manera (en Oracle, por si acaso esto no funciona en su sistema):
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
Añada su user.Firstname y User.lastname a su grupo por la cláusula
Veo un montón buenas notas acerca de la adición de sus campos de nombre al grupo por. Creo que lo haría así, sin embargo:
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
Una de las razones para este enfoque es que hace que sea más fácil para luego volver y conseguir cualquier otra información que desee.