query to find number of employees under each manager - sql

I have an Employee table with columns : Id, Name, Manager_Name
I need to list: count of employees under each manager.
How to form a simple sql query for achieving result?
Note: There may be two managers with same name.
Table:-
create table employee_test (Id int , Name VARCHAR(100), Manager_Name varchar(100));
Input:
ID NAME MANAGER_NAME
-- ------ ------------
1 deep hari
2 mitra hari
3 hari kishan
4 kirti kishan
5 kishan amit
6 jumeet hari
7 fareed deep
8 stuti kishore
My Attempt:-
SELECT m.Name as ManagerName, count(e.Name) as employeesCount
FROM employee_test e
INNER JOIN employee_test m ON e.Manager_Name = m.Name
group by m.Name
My Output:-
MANAGERNAME EMPLOYEESCOUNT
----------- --------------
kishan 2
hari 3
deep 1
But it does not take care of other manager's employee count?
UPDATE:- Question was little unclear to me too as being exactly asked by an interviewer, request to close the question.

I imagine you want this:
select Manager_Name, count(Name)
from Employee
group by Manager_Name

In addition to the response by MJH, if there can be two managers with the same name, there needs to be a way to differentiate them.
Say for instance you have the following (in SQL Server):
create table Employee (Name VARCHAR(100), Manager_Id INT)
create table Managers (Id INT, Name VARCHAR(100))
SELECT d.Manager_Name, d.employeesCount
FROM(
SELECT m.Id, m.Name as Manager_Name, count(e.Name) as employeesCount
FROM Employee e
INNER JOIN Managers m ON e.Manager_Id = m.Id
group by Id, m.Name
) d

Related

Output the names of bosses who manage multiple employees

I have a database of personnel which has an EMPLOYEE_ID, EMPLOYEE_NAME and BOSS_ID. I'm trying to display the employee_name of all bosses who manage 3 or more people. The following query provides me with all the right BOSS_ID's.
SELECT BOSS_ID FROM PERSONNEL
GROUP BY BOSS_ID
HAVING COUNT(BOSS_ID) >= 3
However I wish to only display the EMPLOYEE_NAME of the bosses, not their BOSS_ID. I tried this, but it produced no names at all.
SELECT EMPLOYEE_NAME FROM PERSONNEL
GROUP BY EMPLOYEE_NAME
HAVING COUNT(BOSS_ID) >= 3
Any help would be greatly appreciated.
To get the Manager Name your can do Self Join.
In the below example to get the Manager name you need to get it from P2 Reference.
SELECT DISTINCT P2.EMPLOYEE_NAME AS ManagerName
FROM PERSONNEL P1
JOIN PERSONNEL P2 ON P1.BOSS_ID = P2.EMPLOYEE_ID
GROUP BY P2.EMPLOYEE_NAME
HAVING COUNT(P1.BOSS_ID) >= 3
You can do a JOIN on the same table to obtain the boss's name.
SELECT p.Employee_name, b.Employee_name as "Boss Name"
FROM personnel p
INNER JOIN personnel b ON b.Employee_ID = p.Boss_ID
you can try using a subquery.
SELECT Employee_name
FROM PERSONNEL
where BOSS_ID IN (
SELECT BOSS_ID FROM PERSONNEL
GROUP BY BOSS_ID
HAVING COUNT(BOSS_ID) >= 3
)
db fiddle

self join condition

I have a confusion in self join condition
eg:i have a table named as 'employee' and column as employeeid,name,managerid
just a basic syntax
select e.employeeid,m.managerid
from employee e
left join employee m
**on e.managerid=m.employeeid
or e.employeeid=m.managerid**
please tell me differnce between the text with in **
I think your query is wrong to start with - right now you're getting the employee ID of the employee and the manager ID of the manager. So you're skipping a "generation"
I think you want:
select e.employeeid, m.employeeid
from employee e
left join employee m
on e.managerid=m.employeeid
That will give you the employee IDs in the first column and their manager's ID in the second column.
The second one would be the opposite:
select e.employeeid, m.employeeid
from employee e
left join employee m
on e.employeeid=m.managerid
Would give you the manager ID in the first column and their employee's IDs in the second column. In that case it would make more sense to swap the m and e aliases assuming they stand for manager and employee but that won't change the result.
the first part of your where
e.managerid=m.employeeid
will get your subordinate employees
and the second part
e.employeeid=m.managerid
will get your manager.
selecting m.managerid in your query doesn't really make sense.. if you look at this sample data and query it might make more sense to you.
CREATE TABLE employee (
employeeid INT,
managerid INT
)
INSERT INTO employee
VALUES (1,NULL),
(2,1),
(3,1),
(4,2),
(5,4);
SELECT e.employeeid employee,
m.employeeid relatedemployee,
CASE WHEN e.managerid = m.employeeid THEN 'manager'
ELSE 'employee'
END AS relationship
FROM employee e
LEFT JOIN employee m ON e.managerid = m.employeeid
OR e.employeeid = m.managerid
output:
employee relatedemployee relationship
----------- --------------- ------------
1 2 employee
1 3 employee
2 1 manager
2 4 employee
3 1 manager
4 2 manager
4 5 employee
5 4 manager

does anyone know how to list the empid and the name of all supervisors if supervisors are in employee table too?

I have a table that contains empid, name, salary, hiredate, position and supervisor (which includes empid, not the name). How do I list the empid and name of all supervisors?
The output has to have to columns supervisor (and a list of their empid) and their names. This is the create statement used to create the Employee table:
/* Create table Employee */
IF OBJECT_ID('Employee', 'U') IS NOT NULL
DROP TABLE Employee
GO
CREATE TABLE Employee (
emp_id NCHAR(5),
name NVARCHAR(20),
position NVARCHAR(20),
hire_date DATETIME,
salary MONEY,
bcode NCHAR(3),
supervisor NCHAR(5)
)
I have tried a variety of statements using having statement and count but they don't seem to work.
select emp_id, name from employee where position='manager';
I tried this but it doesn't work. Anyone smart that knows how to do it?
You will have to join the table back on itself:
select a.name, a.position, a.hiredate, a.salary, a.supervisorid,
isnull(b.name, '') as SupervisorName
from EmployeeTable a
left join EmployeeTable b
on a.SupservisorID=b.ID
The left join will make sure that the employees who do not have supervisors are returned, and isnull(b.name, '<NONE>') can be used if you would like to have something other than NULL as a value in those cases.
SELECT e.empid ,ISNULL(b.name, 'No supervisor') SupervisorName
FROM employee e LEFT JOIN employee b
ON e.supervisorid = b.empid
Inner join will leave out the people who do not have a supervisor , Use left join to get all the employees
If you want supervisors only, you just need to select rows whose emp_id values are found in the supervisor column:
SELECT
SupervisorID = emp_id,
SupervisorName = name
FROM dbo.Employee
WHERE emp_id IN (SELECT supervisor FROM dbo.Employee)
;

sql SELECT query - which merges 2 identical tables?

So I have 2 tables. Employee and Draft_Employee. They are identical, except that properties in Draft_Employee allow nulls.
The reason for the 2 identical tables, is that the draft_Employee is a table used for an import procedure - it is a tempoary container. We don't want the data messed up with the production employees.
Now, when a employee has to be imported, the system has to check if the employee already exists in the database.
First it see's if it can find an employee in Employee table with the same EmpID.
If found, it will look at employee in Draft_Employee and find the properties which are NULL or EMPTY. It will then take the value for the same field in Employee table and put it into the empty or NULL fields in draft_Employee
empID name something1 something2 | empID name something1 something2
----- ---- ---------- ---------- | ---- ---- ---------- -----------
1 Casper blahblah blahblah2 | 2 Michael NULL text2fs
2 Michael txttxt |
Right is Employee and left is Draft_Employee.
I want an sql query that produces
empID name something1 something2
----- ---- ---------- ----------
2 Michael txttxt text2fs
The closest I have come, is with LEFT OUTER JOIN but it gives me data from both tables
EDIT: My query. I did not use it before, because the spelling is danish.
SELECT * FROM Kladde_Ressource
LEFT OUTER JOIN Ressource
ON Ressource.RessourceID = Kladde_Ressource.RessourceID
WHERE Kladde_Ressource.EAN = ''
OR Kladde_Ressource.navnLang = ''
OR Kladde_Ressource.navnKort = ''
etc...
I don't entirely grasp your requirement so I am basing my query on the data and required result you've posted.
As to get the results merged into one result set
use COALESCE to get the first non-NULL value from both tables.
use an INNER JOIN to remove the non-matching rows.
Statement
SELECT e.empID
, COALESCE(e.name, de.name) AS name
, COALESCE(e.something1, de.something1) AS something1
, COALESCE(e.something2, de.something2) AS something2
FROM employee e
INNER JOIN draft_employee de ON de.empID = e.empID
This should do the trick:
SELECT Employee.empId,
ISNULL(Employee.name, Draft_Employee.name) AS name,
ISNULL(Employee.something1, Draft_Employee.something1) AS something1,
ISNULL(Employee.something2, Draft_Employee.something2) AS something2
FROM Employee LEFT OUTER JOIN
Draft_Employee ON Employee.empID = Draft_Employee.EmpId
Use the coalesce function to get the first non-null value:
select
e.empID,
coalesce(d.name, e.name),
coalesce(d.something1, e.something1),
coalesce(d.something2, e.something2)
from
Employee e
inner join Draft_Employee d on d.empID = e.empID
How about using UNION and GROUP BY:
SELECT empID, name, MAX(something1) AS something1, MAX(something2) AS something2
FROM (
SELECT empID, name, something1, something2 FROM Employee WHERE empID = 2
UNION
SELECT empID, name, something1, something2 FROM draft_Employee WHERE empID = 2
)
GROUP BY empID, name

New Sql query solution

person_id | manager_id | name |
| | |
-------------------------------
I have to display name of every person with manager name.
Yes its complete table. Thats all I have.
This one should give you all employees that have a manager, with employee_name and manager_name. Replace your_table by your table name.
If you want to get all persons, also that without manager, replace the JOIN by a LEFT JOIN. This would return NULL as manager_name for all persons without manager_id.
SELECT t1.name employee_name, t2.name manager_name
FROM [your_table] t1
JOIN [your_table] t2 ON ( t1.manager_id = t2.person_id )
Which SQL dialect? Here's some TSQL, but I'm vague to the actual question ("every person with manager name"); if you mean "given a manager name, list the people (reports)", then:
SELECT peon.[person_id], peon.[name]
FROM [thetable] mgr
INNER JOIN [thetable] peon
ON peon.manager_id = mgr.[person_id]
WHERE mgr.[name] = #name
ORDER BY peon.[name]
If you mean "list the people, along with their manager's name", then:
SELECT peon.[person_id], peon.[name], mgr.[name] AS [manager]
FROM [thetable] peon
LEFT OUTER JOIN [thetable] mgr
ON mgr.[person_id] = peon.manager_id
ORDER BY peon.[name]
SELECT person.name, manager.name
FROM table person, table manager
WHERE person.manager_id = manager.person_id