how to get manager's name from employ name - sql

How do I find manager name here. Each manager is also an employee.
EmpID Name ManagerId
1 A 3
2 B 1
3 C 2
4 D 5
5 E 1
Expected result is like this
EmpID Name ManagerName
1 A C
2 B A
3 C B
4 D E
5 E A

You have to use Left Join for the desired output..otherwise you will miss some employee who doesn't have managers ..
SELECT e.empid, e.name Employee, ISNULL(e1.name,'') Manager
FROM employee e
LEFT JOIN employee e1 on e.managerid = e1.empid

You can self join the table, and use the joined instance to get the manager's name:
SELECT e.empid, e.name, m.name
FROM employee e
JOIN employee m on e.managerid = m.empid

CREATE TABLE #MYTEMP
(
EmpID INT
,Name VARCHAR(10)
,ManagerId INT
)
INSERT INTO #MYTEMP VALUES
(1,'A',3),( 2,'B',1),(3,'C',2),(4,'D',5),( 5,'E',1)
SELECT EMP.EmpID AS EMPNO,
EMP.Name AS EMPLOYEE,
MGR.Name AS MANAGER
FROM #MYTEMP EMP
JOIN #MYTEMP MGR
ON EMP.ManagerId = MGR.EmpID

Related

How to Query Hierarchical Data in SQL and determine height of each user

I have an Azure SQL table containing all the employees in a company. I use the below query to determine the height of each employee:
WITH emp AS (
SELECT *, 0 AS d
FROM tableA
WHERE Email = '<email>'
UNION ALL
SELECT e.*, emp.d + 1
FROM tableA e INNER JOIN emp
ON e.ManagerId = emp.Id
)
SELECT max(d)
FROM emp e
Is there a more efficient way to determine the height all the employees in the company without recursively running the above query for each employee?
UPDATE:
Here is my table structure:
Id ManagerId Email
1 -1 CEO
2 1 ABC
3 1 DEF
4 2 PQR
5 2 STU
6 3 EPS
7 3 DMN
Is there a more efficient way to determine the height all the employees in the company without recursively running the above query for each employee?
You can do it all with a single recursive query if you start with the top-level employees and recurse down their reporting hierarcies, something like:
WITH emp AS (
SELECT *, 0 AS d
FROM tableA
WHERE ManagerId is null
UNION ALL
SELECT e.*, emp.d + 1
FROM tableA e INNER JOIN emp
ON e.ManagerId = emp.Id
)
SELECT e.Id, e.ManagerId, max(e.d) over () - e.d depth
FROM emp e

Oracle error: ORA-00979: not a GROUP BY expression

Following is the result of my first query (in Oracle). Totals is the total number of employees in each department (so Employee 1-5 are on department#1, employees 6-8 on department#2 etc.)
select a.name, (select count(*) from employee b where a.dname = b.dname group by b.dname) as totals
from employee a;
NAME TOTALS
------------------------------ ----------------
Employee 1 5
Employee 2 5
Employee 3 5
Employee 4 5
Employee 5 5
Employee 6 3
Employee 7 3
Employee 8 3
Employee 9 4
Employee 10 4
Employee 11 4
Employee 12 4
And here is my second query on which employer has less taskhours than 5 (note "taskhours" is a different field than "totals" in the database)
select a.name
from job o, employee a, works w , task t
where w.name=a.name and w.menuid=o.menuid and w.worktype='office' and t.fname = o.fname
group by a.name
having sum(t.taskhours) <5
;
NAME
------------------------------
Employee 3
I want now combine the above, i.e query for the employees who have fewer task-hours than the total employees in the department. I am trying this query
select a.name
from job o, employee a, works w , task t
where w.name=a.name and w.menuid=o.menuid and w.worktype='office' and t.fname = o.fname
group by a.name
having sum(t.taskhours) <(select count(*) from employee b where a.sname = b.sname group by b.sname)
but I get the error:
ERROR at line 5:
ORA-00979: not a GROUP BY expression
Can someone help me find the right query?
Sample data for 1st query:
NAME DNAME
------------------------------ ------------------------------
Employee 1 Dep1
Employee 2 Dep1
Employee 3 Dep1
Employee 4 Dep1
Employee 5 Dep1
Employee 6 Dep2
Employee 7 Dep2
Employee 8 Dep2
Employee 9 Dep3
Employee 10 Dep3
Employee 11 Dep3
Employee 12 Dep3
We can phrase this by putting each of your two queries into subqueries, and then joining them together:
SELECT
e.name,
e.dname,
t1.emp_cnt,
t2.hours_cnt
FROM employee e
LEFT JOIN
(
SELECT dname, COUNT(*) AS emp_cnt
FROM employee
GROUP BY dname
) t1
ON e.dname = t1.dname
LEFT JOIN
(
SELECT a.name, SUM(t.taskhours) AS hours_cnt
FROM works w
INNER JOIN employee a
ON w.name = a.name
INNER JOIN job o
ON w.menuid = o.menuid
INNER JOIN task t
ON t.fname = o.fname
WHERE w.worktype = 'office'
GROUP BY a.name
) t2
ON e.name = t2.name
WHERE
t1.emp_cnt < t2.hours_cnt;
You can simplify the first query as follows
use that as a cte block
with tot_count
as (select dept_id,count(emp_id) as dept_cnt
from employee
group by dept_id)
,less_than_five
as (select a.name
,sum(t.taskhours) as sum_taskhours
,max(a.dept_id) as dept_id_of_emp
from job o,
employee a,
works w ,
task t
where w.name=a.name
and w.menuid=o.menuid
and w.worktype='office'
and t.fname = o.fname
group by a.name
)
select *
from less_than_five a
join tot_count b
on a.dept_id_of_emp=b.dept_id
where less_than_five.sum_taskhours<=b.dept_cnt

how to display records which is present in employee but not present in department table

i want to get records which is present in employees table but not in department
i.e (Employees - department)
output should be like this
Employee(ID,Name), Department(Id,Name)
i tried this
select * from Employee as e
left join Department as d on e.DeptId = d.ID
sample data
ID Name DeptId Salary ID Name
1 krishna 1 5000 1 developer
2 rakesh 2 8000 2 trainer
3 sanjay 3 9000 3 programmer
4 swapna 4 6000 4 seo
6 shiva 6 4000 NULL NULL
i want to show records of shiva because he is in table employee but not in department table in sql server
Either use an OUTER JOIN as you've already done and filter by d.ID is null(as Dave has already shown). Or use NOT EXISTS which is my favorite:
select e.*
from Employee e
where not exists
(
select 1 from Department d
where e.DeptId = d.ID
)
Pros and cons of all approaches:
Should I use NOT IN, OUTER APPLY, LEFT OUTER JOIN, EXCEPT, or NOT EXISTS?
I had a little difficulty understanding the question but with your existing query a WHERE clause could be used to only show records that don't have an appartment.
select * from Employee as e
left join Department as d on e.DeptId = d.ID
WHERE d.ID is null
Alternatively
select
*
from Employee as e
WHERE e.ID not in (SELECT d.ID FROM Department d)

Sql query for 3 tables checks either of table

I am having 3 tables
1 : Employee
2 : Department
3 : Experts
I want the experts which belong to CmpId = 1
Employee :
id CmpId
1 2
2 1
3 1
Department
id CmpId
1 1
2 2
3 2
Experts :
id EmployeeId DepartmentId
1 1 2
2 2 null
3 null 1
4 2 1
5 null null
Let me guess that NULL in the expert table means that someone is an expert for all departments. If so:
select e.employeeid
from experts e join
departments d
on e.departmentid = d.id or e.departmentid is null;
If I understand the question correctly, the desired results based on the sample data should be Expert ID's 2,3 and 4.
Expert ID 2 has an Employee ID of 2, which has a CmpID of 1.
Expert ID 3 has a Department ID of 1, which has a CmpID of 1.
Expert ID 4 has an Employee ID of 2, which has a CmpID of 1 and a Department ID of 1 which has a CmpID of 1.
If this is in fact the desired result set, I would write the following query.
SELECT ex.id, ex.EmployeeID, ex.DepartmentID
FROM #Experts ex
LEFT JOIN #Department dep
ON ex.DepartmentID = dep.id
LEFT JOIN #Employee emp
ON ex.EmployeeID = emp.id
WHERE dep.CmpID = 1 OR emp.CmpID = 1
That will yield the following results.
id EmployeeID DepartmentID
2 2 NULL
3 NULL 1
4 2 1
INNER JOIN the three tables
If they need to be CmpId = 1 in BOTH (this returns nothing in your sample data but assuming it is a larger data set)
SELECT e.id, e.EmployeeId, e.DepartmentId
FROM Experts e
FULL OUTER JOIN Department d ON e.DepartmentId = d.id
FULL OUTER JOIN Employee em ON e.EmployeeId = em.id
WHERE d.CmpId = 1 AND em.CmpId = 1
If they need to be CmpId = 1 in Either
SELECT e.id, e.EmployeeId, e.DepartmentId
FROM Experts e
FULL OUTER JOIN Department d ON e.DepartmentId = d.id
FULL OUTER JOIN Employee em ON e.EmployeeId = em.id
WHERE d.CmpId = 1 OR em.CmpId = 1

Get the output based on column in the same table

I have a table which looks like this:
Employee table:
Employee_id E_Name Manager_Id
-------------------------------
1 p -
2 q 1
3 r 1
4 s 2
Here column Manager_Id denotes the manager's employee Id. Meaning for p there is no manager. for q and r employee with id 1 is manager (p). and for s employee with emp id 2 is manager.
I want to build a query which will return below result:
Employee_id E_Name Manager_Name
-------------------------------
1 p -
2 q p
3 r p
4 s q
table here has manager name instead of id.
How to achieve above? Thanks in advance
It can easily be done with a LEFT OUTER JOIN:
Try this:
SELECT a.EMPLOYEE_ID, a.E_NAME, b.E_NAME
FROM EMPLOYEE a left outer join EMPLOYEE b
on A.MANAGER_ID = B.EMPLOYEE_ID
you did not mentioned the database provider, but for MySQL, it is:
SELECT e.employee_id, e.e_name,COALESCE(m.e_name,'-') AS Manager_Name
FROM employee e
LEFT JOIN employee m ON m.employee_id = e.manager_id
Please try:
select
Employee_id,
E_Name,
(select E_Name from YourTable b where b.Employee_id=a.Manager_Id) as Manager_Name
from YourTable a