Qualcuno mi può mostrare perché la mia query SQL non funziona (vedi dettagli)?
-
22-08-2019 - |
Domanda
Ho usato la seguente query per trovare i duplicati:
SELECT userID,
COUNT(userID) AS NumOccurrences
FROM userDepartments
GROUP BY userID
HAVING ( COUNT(userID) > 1 )
Allora ho provato ad aggiungere un inner join così ho potuto vedere i nomi utente che corrispondono, che sono memorizzati in una tabella diversa.
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 )
Ma mi ha dato un errore dicendo che users.firstname non faceva parte di qualche funzione di aggregazione o qualcosa del genere ...
Qualcuno sa come posso ottenere il conteggio, solo gli utenti spettacolo con più di 1 reparto, e anche ottenere il nome e il cognome fuori all'altro tavolo in modo da poter ottenere un elenco di nomi di utenti che hanno più di un reparto assegnato?
EDIT: Questa è la query che ha finito per lavorare per me ...
SELECT firstname, lastname
FROM tbl_users
WHERE (userID IN
(SELECT userID
FROM tbl_usersDepts
GROUP BY userID
HAVING (COUNT(userID) > 1)))
Soluzione
Vorrei riorganizzare la domanda un po '....
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
Altri suggerimenti
Il motore SQL non sa che hai un solo nome utente per ogni userid, quindi bisogna gruppo dal nome e cognome, nonché dall'utente id.
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 )
Se non lo fai gruppo per nome e cognome, il motore non si sa che cosa dovrebbe fare se ottiene più di un valore di cognome per un dato userid. Dicendo al gruppo da tutte e tre valori, sa che se v'è più di una riga per userid, dovrebbe restituire tutte le righe. Anche se questo non dovesse accadere, il motore non è abbastanza intelligente, in questo caso a decidere che da sola.
Si potrebbe anche fare in questo modo:
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
Gruppo da parte di tutti e tre: l'userDepartments.userID, users.firstname, e users.lastname
È necessario includere user.firstname e users.lastname nella vostra clausola GROUP BY - in quanto non sono valori aggregati (si noti che MySQL realtà non supporta la sintassi che hai usato nella query, ma non è di serie).
Se si fa un "gruppo da" poi tutto nella parte di "selezionare" o deve essere:
-
di cui il "gruppo da" clausola o
-
Il risultato di una funzione di aggregazione (come count ())
Lo farei in questo modo (in Oracle, nel caso in cui questo non funziona nel 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
Aggiungi il tuo user.Firstname e User.lastname al gruppo dalla clausola
Vedo un sacco buone note su come aggiungere i vostri campi di nome al gruppo. Penso che mi piacerebbe fare in questo modo, però:
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 delle ragioni di questo approccio è che rende più facile per poi tornare indietro e prendere qualsiasi altra informazione che si potrebbe desiderare.