self join condition - sql

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

Related

How to get count of registered sets combination and non registered sets as '0' value

I had 2 individual tables named manager, employee.
In the manager table we have ID, a list of managers, in the employee table we have ID, a list of employees, and another column named manager_id as a foreign key. Total 20 combinations
Now there is another table called registration which has manager and employee as separate columns along with other columns. I want a select query of All 20 manager and employee combinations for which non registered combinations should appear as '0'.
I tried with below query but not getting expected output
Query:
select r.manager,r.employee,count(*)
from registration r
group by r.manager,r.employee
union all
select s.manager, i.employee,null
from manager m, employee e
where m.id = e.manager_id
---> It is showing output in a way where the registration table list is coming first with count and later with all 20 combinations as null value in count column
I don't know the exact column names of the registration table, but the query should be something like this:
select
e.id,
e.manager_id,
(case r.employee_id is null then 0 else 1 end) as is_registered
from
employee e
left join registration r
on r.employee_id = e_id and r.manager_id = e.manager_id
This is the query I modified
select m.manager, e.employee,
sum(case when r.employee is null then 0 else 1 end) as total
from employee e
left join registration r on r.employee = e.employee
left join manager m on m.id = e.manager_id
group by m.manager, e.employee, r.employee

My SQL Join is only producting half the right aggregate output

SELECT E.DNO as DeptNum, COUNT(E.SSN) as EmployeeCount, COUNT(D.ESSN) as DependentCount
FROM Dependent D
RIGHT OUTER JOIN Employee E ON D.ESSN = E.SSN
GROUP BY E.DNO
The goal is to find the total number of employees and total number of dependents for every department. I am utilizing an Employee Table that features Employee, SSN, Department Number and a Dependent Table that has Dependent SSN, Birthdate, and Gender.
The output should be as follows
Dept Num Employee Count DependentCount
1 1 0
2 3 7
3 5 2
But, instead I am getting
Dept Num Employee Count DependentCount
1 1 0
2 9 7
3 4 2
One thing of note is the dependent's SSN is equivalent to the parent's SSN - that is the only way to define the relationship between the tables. Also, I know I need an outer join because we want to list ALL departments, despite the fact there are 0 mentions of it for Dept 1 in Dependent Table.
Can anyone tell me why this isn't working?
Try using distinct so things don't get double counted:
SELECT E.DNO as DeptNum, COUNT(DISTINCT E.SSN) as EmployeeCount,
COUNT(DISTINCT D.ESSN) as DependentCount
FROM Employee E LEFT JOIN
Dependent D
ON D.ESSN = E.SSN
GROUP BY E.DNO

How to combine two columns from different tables that have a similar name but have different values in SQL Server

I have three tables (example) STAFF, STU, EMP.
I want to combine the column EMPID in table STAFF and table EMP into 1 column?
My previous query is like this,
SELECT *
FROM STU s
FULL OUTER JOIN STAFF st ON st.STAFFID = STUID
FULL OUTER JOIN EMP e ON s.STUID = st.EMPID
The result is like this
The expected result is just like the above screenshot, but I want to join EMPID into one column only.
UPDATE:
I tried using this query:
SELECT
stu.stuid, stu.stuname, stu.stucode,
s.staffid, s.staffname, s.staffcode,
emp.empname, emp.empcode,
COALESCE (emp.empid, staff.staffid) AS col
FROM
STU, Staff, EMP
FULL OUTER JOIN
STAFF s ON s.STAFFID = stu.STUID
FULL OUTER JOIN
EMP e ON stu.STUID = s.EMPID
but it displays an error like this
Use below query to get the desired result.
SELECT s.StuID, s.StuName, s.Stucode, st.StaffId, st.StaffName, st.Staffcode, isnull(st.EmpId, e.EmpId) EmpId, e.EmpCode, e.EmpName
FROM STU s FULL outer JOIN
STAFF st
ON st.STAFFID = STUID FULL OUTER JOIN
EMP e
ON s.STUID = st.EMPID
Note: You will get the one emp Id column as needed. If Staff emp id is not null then staff emp id will be displayed else employee emp id will be displayed

Self Join with Correlated Subquery

I need to find an employee with a salary greater than their Manager. For this, I used to following query and it works;
SELECT
e1.EmpID
,e1.EmpName
,e1.EmpSalary
,e1.ManagerID
FROM empsalary e
INNER JOIN empsalary e1 ON e.EmpID = e1.ManagerID
WHERE e1.EmpSalary > e.EmpSalary
But following one is not working. I want to know why it is not? Why it's result is null? What should be correct format?
SELECT *
FROM empsalary as e
WHERE e.empsalary=(
SELECT e1.empsalary
FROM empsalary as e1
WHERE e.EmpID = e1.ManagerID
AND e1.EmpSalary > e.EmpSalary)
Sample data and code here;
EmpID EmpName EmpSalary ManagerID
----------- ---------- -------------------- -----------
1 Neevan 100000 6
2 Mukesh 30000 6
3 Disha 50000 6
4 Martin 90000 6
5 Roy 170000 6
6 Anvesh 168000 NULL
CREATE TABLE empsalary
(
EmpID INT
,EmpName VARCHAR(10)
,EmpSalary BIGINT
,ManagerID INT
)
INSERT INTO empsalary
VALUES
(1,'Neevan',100000,6)
,(2,'Mukesh',30000,6)
,(3,'Disha',50000,6)
,(4,'Martin',90000,6)
,(5,'Roy',170000,6)
,(6,'Anvesh',168000,NULL)
Your correlations are all backwards. The right way is:
SELECT e.*
FROM empsalary e
WHERE e.empsalary > (SELECT m.empsalary
FROM empsalary m
WHERE m.EmpID = e.ManagerID
);
Notice that I have used the m table alias for the manager record. This helps to follow the logic.
There's no need for me to re-write how to do it, as Gordon has done a good enough job already, but I can explain why yours returned null...
For me to answer this, I needed to re-write yours slightly to help me to read it. It is essentially the same as yours. Also, similarly to how Gordon has done, I've substituted e for m and e1 for e. I've also called your tables tblSalaries, so that the table names aren't the same as the column name:
SELECT *
FROM tblSalaries as m
WHERE m.empsalary=(
SELECT e.empsalary
FROM tblSalaries as e
WHERE e.ManagerID = m.EmpID
AND e.EmpSalary > m e.EmpSalary)
If we work backwards and interpret the last part firstly:
...
(
SELECT e.empsalary
FROM tblSalaries as e
WHERE e.ManagerID = m.EmpID
AND e.EmpSalary > m.EmpSalary)
Firstly, WHERE m.ManagerID = e.EmpID is saying 'Find all employees in e who's manager ID is the same as the employee ID in m'. Considering there is only one managerID (6), then records 1-5 from e will all match the manager record, on m (6) on this.
Your next clause AND e.EmpSalary > m.EmpSalary is finding those who's salary is greater than the managers'. Therefore, you are left with record 5 (Roy) as you intended.
Now to return to your main query:
SELECT *
FROM tblSalaries as m
WHERE m.empsalary= (...tblSalaries as e...)
We have established that table e in the brackets has returned Roy, but we have also established that it only matches records in table m, where m is a manager. Ultimately, you are asking then to find where the manager's salary = Roy's salary; the answer, null.

SQL subquery Total/Count

I am trying to write a query that lists the name of a manager and the number of people they manage.
In the Manager table we have the managers name and id.
In the Employee table we have the employees name, id and managerID.
I don't understand how to get the count of the employees that a manager manages.
SELECT COUNT(e.EmpID), m.ManagerID
FROM Employee e
INNER JOIN Manager m
ON e.ManagerID= m.ManagerID
GROUP BY m.ManagerID
SELECT m.Name, COUNT(e.id) AS NumberOfEmployeesManaged
FROM Manager m INNER JOIN Employee e ON m.id = e.managerID
GROUP BY m.Name
That should do it I think, just a simple count of the employee ids after joining the manager and employee tables, grouped on manager name.
SELECT count(emp.empid), mgr.managerid
FROM Employee emp
INNER JOIN Manager mgr ON emp.managerid=mgr.managerid
GROUP BY mgr.managerid;
I don't know if you can use the COUNT aggregator in a JOIN. But you can run 2 queries. One would select the manager's name & id. The 2nd would look like this:
$id = the manager's id
SELECT COUNT(*) FROM Employee WHERE managerID=$id
Alternately, you could not use COUNT and run a query like this:
SELECT id FROM Employee WHERE managerID=$id
Then the # of resulting rows would be the count of employees managed by the manager.