Question

I used the following query to find duplicates:

SELECT userID,
COUNT(userID) AS NumOccurrences
FROM userDepartments
GROUP BY userID
HAVING ( COUNT(userID) > 1 )

I then tried adding an inner join so I could see the user names that match, which are stored in a different table.

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 )

But it gave me an error saying that users.firstname was not part of some aggregate function or something...

Does anyone know how I can get the count, only show users with more than 1 department, and also get the first and last name out of the other table so I can get a list of users names who have more than one department assigned?

EDIT: THIS IS THE QUERY THAT ENDED UP WORKING FOR ME...

SELECT     firstname, lastname
FROM         tbl_users
WHERE     (userID IN
                          (SELECT     userID
                            FROM          tbl_usersDepts
                            GROUP BY userID
                            HAVING      (COUNT(userID) > 1)))
Was it helpful?

Solution

I would rearrange the query a little bit....

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

OTHER TIPS

The SQL engine doesn't know that you only have one username per userid, so you have to group by firstname and lastname as well as by user 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 )

If you don't group by firstname and lastname, the engine doesn't know what it's supposed to do if it gets more than one value of firstname for a given userid. By telling it to group by all three values, it knows that if there is more than one row per userid, it should return all those rows. Even though this shouldn't happen, the engine isn't smart enough in this case to decide that on its own.

You could also do it this way:

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

Group by all three: the userDepartments.userID, users.firstname, and users.lastname

You need to include user.firstname and users.lastname in your GROUP BY clause - as they are not aggregate values (note that MySQL does actually support the syntax you've used in your query, but it is not standard).

If you do a "group by" then everything in the "select" portion either needs to be:

  1. Mentioned in the "group by" clause or

  2. The result of an aggregate function (like count())

I would do it this way (in Oracle, just in case this doesn't work in your system):

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

Add your user.Firstname and User.lastname to your group by clause

I see a lot good notes about adding your name fields to the group by. I think I'd do it like this, though:

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

One reason for this approach is that it makes it easier to then go back and get any other information you might want.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top