tags:

views:

114

answers:

4
person_id | manager_id | name |
          |            |      |
-------------------------------

Query to find name of manager who supervises maximum number of employees?

Added: This is the only table. Yes self-referencing. DB is mysql. Recursive queries will also do.

+4  A: 

This query returns the manager_id and manager_name of the manager with the maximal number of employees.

The trick is in the HAVING clause, which allows aggregates and counts over multiple rows.

SELECT manager_id,name, count(*) 
    FROM table 
    GROUP BY manager_id, name
    HAVING max(count(*));

You can read more in the short but informative w3schools.com HAVING clause tutorial.

If the manager_id references a person id in the same table, Svinto's answer might be more suitable.

Adam Matan
+1 This is smarter than the question, as it allows for a tie.
egrunin
There is no manager_name column.
svinto
I stand corrected - changed `manager_name` to `name`.
Adam Matan
You have to change that also in the `GROUP BY` clause.
Felix Kling
Hmm, last edit breaks the query -- see my answer.
egrunin
@Felix thanks, corrected - TOO LITTLE SLEEP, TOO LITTLE COFFEE.
Adam Matan
SQL Error - Invalid use of group function
AJ
+3  A: 
SELECT name 
FROM table 
WHERE person_id = (
    SELECT manager_id 
    FROM table 
    GROUP BY manager_id 
    HAVING max(count(*)))
svinto
+1 ...and this one noticed that we need the name, not the id, but it doesn't allow for a tie.
egrunin
Unknown column 'count' in 'having clause'
AJ
+1 for noticing self reference; I think it should be `HAVING max(count(*))
Adam Matan
Should be max(count(*)). Still doesn't allow for a tie, however.
egrunin
SQL Error - Invalid use of group function
AJ
A: 

Assuming manager_id have a reference to person_id and name of table: table_name

SELECT name FROM (
  SELECT manager_id
  FROM table_name
  GROUP BY manager_id
  ORDER BY COUNT(*) DESC
  LIMIT 1
) t
INNER JOIN table_name ON t.manager_id = table_name.person_id

edit: Removed HAVING MAX COUNT, added ORDER BY COUNT DESC LIMIT 1 in subquery

Alex LE
-1: Invalid use of group function.
Mark Byers
@Mark, you're right, returned to my previous answer.
Alex LE
Sorry but this still doesn't work for `(1, NULL, 'Foo'),(2, NULL, 'Bar'), (3, 1, 'Baz')` as it returns no rows instead of FOO. Sorry for picking on your answer in particular - everyone else here has made the same mistake too. I chose yours because it had no comments and others have more serious errors too that have already been pointed out. See my answer for a working version.
Mark Byers
+1  A: 

It's not entirely clear to me what you want, so if this isn't what you want please clarify your question.

This query returns just one of the managers if there is a tie:

SELECT T2.name FROM (
    SELECT manager_id
    FROM table1
    WHERE manager_id IS NOT NULL
    GROUP BY manager_id
    ORDER BY count(*) DESC
    LIMIT 1
) AS T1
JOIN table1 AS T2
ON T1.manager_id = T2.person_id

Result of query:

Bar

Here's a query that fetches all managers with the tied maximum count in the case that there is a tie:

SELECT name FROM (
    SELECT manager_id, COUNT(*) AS C
    FROM person
    WHERE manager_id IS NOT NULL
    GROUP BY manager_id) AS Counts
JOIN (
    SELECT COUNT(*) AS C
    FROM person
    WHERE manager_id IS NOT NULL
    GROUP BY manager_id
    ORDER BY COUNT(*) DESC
    LIMIT 1
) AS MaxCount
ON Counts.C = MaxCount.C
JOIN person
ON Counts.manager_id = person.person_id

Result of the second query:

Foo
Bar

Here's my test data:

CREATE TABLE Table1 (person_id int NOT NULL, manager_id nvarchar(100) NULL, name nvarchar(100) NOT NULL);
INSERT INTO Table1 (person_id, manager_id, name) VALUES
(1, NULL, 'Foo'),
(2, '1', 'Bar'),
(3, '1', 'Baz'),
(4, '2', 'Qux'),
(5, '2', 'Quux'),
(6, '3', 'Corge');
Mark Byers
works perfectly!
AJ
thank you!!!! Mark
AJ
You're welcome. It took me a long time to figure out exactly what you wanted. Thanks for being patient with my constant questions. :) Next time you post a similar question, I'll probably ask you very similar questions, so it would be a good idea to put the answers in your question from the start.
Mark Byers