From employee table below, I need to retrieve an employee and the manager. Can someone help me? Thanks in advance.
tblEmployee:
empId empName manID
1 A
2 B 1
3 C 2
Output:
Name Manager
A -
B A
C B
A pair of rudimentary approaches would be
SELECT
'Name' = empName
, 'Manager' = (SELECT empName FROM tblEmployee WHERE empID = e.manID)
FROM tblEmployee e
or
SELECT
'Name' = e.empName
, 'Manager' = ISNULL(m.empName, 'none')
FROM tblEmployee e
LEFT JOIN tblEmployee m
ON e.manID = m.empID
There is probably a better approach depending on the DBMS you are using.
You simple need to join the table with itself:
For mysql it would be :
SELECT
t1.empName AS 'Name',
IFNULL(t2.empName, '-') AS 'Manager'
FROM
myTable t1
LEFT JOIN
myTable t2
ON
t1.manID = t2.empId
t1 now would be the base-user, while t2 would contain the manager, if present. If there is no manager, t2.empName will be null and then be replaced with a - by the ifnull function.
Make use of Right and self joins
select t2.empName, t1.empName as Manager from tblEmployee t1
right Join tblEmployee t2 on t1.empID = t2.manID
order by empName
Related
Join multiple table and concatenate multiple rows into one for distinct department names.
I was able to do it on table EmpDepartment but I need to join all table.
Expected output like this.
Need Query
EmpID
EmpName
DepartmentName
1
A
q,w,e
2
B
Null
SELECT
p.EmpID,
EmpName,
STRING_AGG(DepartmentName,',') as DepartmentName
FROM
EmpPayroll p
LEFT OUTER JOIN
EmpDepartment e on e.EmpID=p.EmpID
LEFT OUTER JOIN
Department d on d.deptID=e.deptID
GROUP BY
p.EmpID,
EmpName
if you're on SQL Server 2017 or later.
https://learn.microsoft.com/en-us/sql/t-sql/functions/string-agg-transact-sql?view=sql-server-ver15
I updated as per your request.
If you are using SQL Server 2017 and above Versions
SELECT ED.EmpId
,EP.EmpName
,STRING_AGG(D.DepartmentName,',') AS DepartmentName
FROM EmpPayroll EP
LEFT JOIN EmpDepartment ED
ON EP.EmpId = ED.EmpId
LEFT JOIN Department D
ON D.DeptId = ED.DeptId
Group By ED.EmpId, EP.EmpName
and for SQL Server 2016 and Below Versions
;WITH Partitioned AS
(
SELECT EP.EmpId, EP.EmpName,D.DepartmentName,
ROW_NUMBER() OVER (PARTITION BY ED.EmpId ORDER BY D.DepartmentName) AS NameNumber,
COUNT(*) OVER (PARTITION BY ED.EmpId) AS NameCount
FROM EmpPayroll EP
LEFT JOIN EmpDepartment ED
ON EP.EmpId = ED.EmpId
LEFT JOIN Department D
ON D.DeptId = ED.DeptId
),
Concatenated AS
(
SELECT
EmpId,
CAST(DepartmentName AS nvarchar) AS DepartmentName,
EmpName,
NameNumber,
NameCount
FROM Partitioned
WHERE NameNumber = 1
UNION ALL
SELECT
P.EmpId,
CAST(P.DepartmentName + ', ' + C.DepartmentName AS nvarchar),
P.EmpName,
P.NameNumber,
P.NameCount
FROM Partitioned AS P
INNER JOIN Concatenated AS C
ON P.EmpId = C.EmpId
AND P.NameNumber = C.NameNumber + 1
)
SELECT
EmpId,
EmpName,
DepartmentName
FROM Concatenated
WHERE NameNumber = NameCount
Can you please help me, I don't know how to create this query. I am a front end dev.
Expected result should be table with 2 columns
Name(one) DepartmentName(many)
The tables and their relationship are shown in this image:
You can do this with a couple of INNER JOINS. You don't need to reference the Location table in this query because Employee.LocationId is the same as EmployeeDepartment.LocationId.
This simple query will return all employee names and all department names they are related to. The employee name may be repeated, as this query puts only one department name in the column, so if an employee is in two departments, you get the employee name twice.
SELECT
EmployeeName = e.Name
,DepartmentName = d.Name
FROM Employee e
INNER JOIN EmployeeDepartment ed ON ed.LocationId = e.LocationId
INNER JOIN Department d ON d.id = ed.DepartmentId
This query is a bit more complicated, but returns each employee name only once, and the department names will be a comma-separated string of names. This is accomplished by using STUFF() in conjunction with FOR XML.
;WITH EmployeesAndDepartments AS
(
SELECT
EmployeeName = e.Name
,DepartmentName = d.Name
FROM Employee e
INNER JOIN EmployeeDepartment ed ON ed.LocationId = e.LocationId
INNER JOIN Department d ON d.id = ed.DepartmentId
)
SELECT
ead.EmployeeName
,Departments = STUFF((
SELECT ',' + DepartmentName
FROM EmployeesAndDepartments
FOR XML PATH('')
) , 1, 1, ''
)
FROM EmployeesAndDepartments ead
GROUP BY ead.EmployeeName
This should work
SELECT
e.Name
, d.Name AS DepartmentName
FROM
Employee e
LEFT OUTER JOIN
EmployeeDepartment ed
ON e.LocationId = ed.LocationId
LEFT OUTER JOIN
Department d
ON ed.DepartmentId = d.id
Note that the use of LEFT OUTER JOIN will return the employee even if they don't have a corresponding record in EmployeeDeparatment and/or Department. If you only want to retrieve employees that do have corresponding EmployeeDepartment and Department records, use INNER JOIN instead
I have 2 tables,
The first one is called emp, and has 2 columns called id and name
The second one is called dep, and has columns called id and empid and nameOfDep
if I want to list all emp that have X dep, but don't have Y dep
This is an example I use
Select e.id, e.name
from emp e
where e.id in (Select empid from deptid where deptid=X)
and e.id not in (Select empid from deptid where deptid=Y);
How I can make it using JOIN instead of with subqueries?
An IN can be converted into an INNER JOIN. A Not IN can be converted to LEFT JOIN / NULL Test. Sometimes called an ANTI JOIN.
SELECT e.id,
e.name
FROM emp e
INNER JOIN deptid D_X
ON e.empid = d_x.empid
AND deptid = 'X'
LEFT JOIN deptid D_Y
ON e.empid = d_Y.empid
AND deptid = 'Y'
WHERE d_Y.empid IS NULL
Also I'm making the assumption that when you wrote deptid = X that you meant X to be a literal string and not a field name
SELECT e.id, e.name
FROM emp e
INNER JOIN dep d ON (e.deptID = d.deptID AND d.deptID NOT y)
Add the Department ID to the employee record and then join on that.
EDIT
My bad, updated.
EDIT
Helps to read, go with Conrad's answer.
I have two tables.
Employee
EmployeeID, EmployeeName, DocumentType
and
DocumentType
DocumentTypeID, DocumentType
There are Multiple Employees and Multiple DocumentTypes.
For each employee, I am trying to display which DocumentTypes do not exist.
I cant seem to do this for each EmployeeID/Employee Name.
I can only get a list of DocumentTypes that dont exist for ALL employees.
Can I do this without a cursor going through each EmployeeID?
EDIT Better version
select distinct e.EmployeeID, e.EmployeeName, t.DocumentTypeID, t.DocumentType
from Employee e
cross join DocumentType t
left join Employee e2 on e2.EmployeeID = e.EmployeeID and t.DocumentTypeID = e2.DocumentTypeID
where e2.EmployeeID is null
Original -
This works but doesn't feel like the most elegant solution
select distinct e.EmployeeID, e.EmployeeName, dt.DocumentTypeID, dt.DocumentType
from Employee e
outer apply (
select * from DocumentType t
where not exists (
select 1
from Employee e2
where e2.DocumentTypeID = t.DocumentTypeID
and e2.EmployeeID = e.EmployeeID)
) dt
I guess you are looking for data something like this
EmployeeID EmployeeName DocumentTypeNotMapped
1 abc doctype1, doctype3, doctype4
2 def doctype3, doctype2, doctype7
Using the query
SELECT ET.EmployeeID, ET.EmployeeName,
SELECT LEFT(DocumentType, LEN(DocumentType) - 1)
FROM (
SELECT DISTINCT DocumentType + ', '
FROM DocumentTypeTable
WHERE DocumentType != ET.DocumentType
FOR XML PATH ('')
) D (DocumentType)
FROM EmployeeTable ET
assuming you are using sql server
;with cte as (
select E.EmployeeID, E.DocumentType,D.DocumentTypeID from Employee E
left outer join Document D
on E.DocumentType<>D.DocumentTypeID),
cte1 as (select EmployeeID,DocumentTypeID from cte
group by EmployeeID,DocumentTypeID
having count(*)>1)
select * from cte1
union all
select EmployeeID,DocumentTypeID from cte where EmployeeID not in
(select EmployeeID from cte1)
order by EmployeeID,DocumentTypeID
Department(DepartID,DepName)
Employees(Name,DepartID)
What i need is the Count of Employees in the Department with DepName.
If you are using SQL Server version 2005 or above, here is another possible way of getting employees count by department.
.
SELECT DPT.DepName
, EMP.EmpCount
FROM dbo.Department DPT
CROSS APPLY (
SELECT COUNT(EMP.DepartId) AS EmpCount
FROM dbo.Employees EMP
WHERE EMP.DepartId = DPT.DepartId
) EMP
ORDER BY DPT.DepName
Hope that helps.
Sample test query output:
I'd use an outer join rather than a subquery.
SELECT d.DepName, COUNT(e.Name)
FROM Department d
LEFT JOIN Employees e ON e.DepartID = d.DepartID
GROUP BY d.DepartID, d.DepName
SELECT d.DepName, COUNT(e.Name)
FROM Department d
LEFT JOIN Employees e
ON d.DepartID = e.DepartID
GROUP BY d.DepName
No need for a subquery.
SELECT dep.DepName, COUNT(emp.Name)
FROM DepName dep
LEFT OUTER JOIN Employees emp ON dep.DepartID = emp.DepartID
GROUP BY dep.DepName
SELECT COUNT(DISTINCT Name) FROM
Department AS d, Employees AS e
WHERE d.DepartID=e.DepartID AND d.DepName = '$thename'
And to avoid using a group by and save you a Sort operation in the queryplan:
SELECT
Department.DepName,
(SELECT COUNT(*)
FROM Employees
WHERE Employees.DepartID = Department.DepartID)
FROM
Department