Need a query to find employees that have not paid into retirement - sql

My first post here and hoping for some help. I have a need to create a report that shows employees that have never paid into retirement. I need to pull information from 3 tables. Employees have paid into retirement if they have specific deduction codes (7001 through 7006). I have the following tables and columns.
Employee
Employee.empid
Employee.fname
Employee.lname
Employee.jobclass
EarnHistory
EarnHistory.empid
EarnHistory.hoursworked
EarnHistory.checknumber
EarnHistory.checkdate
DeductionHistory
DeductionHistory.empid
DeductionHistory.deductioncode
DeductionHistory.checknumber
DeductionHistory.checkdate
Query needs to pull in empid, fname, lname, hoursworked, deductioncode
Where the employee has never paid into deduction code 7001 through 7006.
I've tried unsuccessfully to use NOT EXISTS

Something like this should work:
SELECT E.empid, E.fname, E.lname, EH.hoursworked, DH.deductioncode
FROM Employee E
INNER JOIN EarnHistory EH ON E.empid = EH.empid
INNER JOIN DeductionHistory DH ON E.empid = DH.empid
LEFT JOIN DeductionHistory DH2 ON E.empid = DH2.empid
AND DH2.deductioncode IN (7001,7002,7003,7004,7005,7006)
WHERE DHD2.empid IS NULL
This depends on your deductioncode data type. You could use BETWEEN, <>, or add apostrophes if varchar.
You could also use NOT EXISTS:
SELECT E.empid, E.fname, E.lname, EH.hoursworked, DH.deductioncode
FROM Employee E
INNER JOIN EarnHistory EH ON E.empid = EH.empid
INNER JOIN DeductionHistory DH ON E.empid = DH.empid
WHERE NOT EXISTS (SELECT *
FROM DeductionHistory
WHERE deductioncode IN (7001,7002,7003,7004,7005,7006)
AND E.empid = DeductionHistory.empid)
Good luck.

select Employee.empid, Employee.fname , Employee.lname,EarnHistory.hoursworked, DeductionHistory.deductioncode from Employee
join EarnHistory using('empid')
join DeductionHistory using('empid')
LEFT JOIN DeductionHistory dh ON Empployee.empid = dh.empid
AND DH.deductioncode IN (7001,.......,7006)
WHERE DHD.empid IS NULL

SELECT E.empid, E.fname, E.lname, EH.hoursworked, DH.deductioncode
FROM Employee E, EarnHistory EN, DeductionHistory DH
WHERE E.empid = EH.empid
AND E.empid = DH.empid
AND E.empid <> (SELECT empid
FROM DedutionHistory
GROUP BY empid
HAVING deductioncode >= 7001
AND deductioncode <= 7006)

Related

I need to get number of employees per depatment

This gets me the number of employees per department
SELECT department, COUNT(idEmployees) empCount
FROM employees
GROUP BY department;
You could join on departments to get the buildingID, and then group by that:
SELECT buildingID, COUNT(*)
FROM employees e
JOIN department d ON e.department = d.departmentID
GROUP BY buildingID
i think this is the solution
select d.buildingID, count(e.ID)
from department d
inner join employees e
on d.departmentID = e.department
group by d.buildingID
This question can be answered in two ways. Firstly, if all employees of a department must be attached in a building. Secondly few employees of a department are attached to a building.
For one where employees are attached to a building it's mandatory
SELECT d.buildingId
, COUNT(e.id) count_employee
FROM departments d
INNER JOIN employees e
ON d.departmentid = e.department
GROUP BY d.buildingId
For second where employees are attached to a building but it's optional. In that case LEFT JOIN is used.
SELECT b.buildingId
, COALESCE(t.count_employee, 0) count_employee
FROM building b
LEFT JOIN (SELECT d.buildingId
, COUNT(e.id) count_employee
FROM departments d
INNER JOIN employees e
ON d.departmentid = e.department
GROUP BY d.buildingId) t
ON b.buildingId = t.buildingId
If a building is attached with multiple departments and one employee is assigned with multiple departments then count building wise same employee is only onetime not multiple times. In that case DISTINCT keyword is used inside COUNT().
SELECT d.buildingId
, COUNT(DISTINCT e.id) count_employee
FROM departments d
INNER JOIN employees e
ON d.departmentid = e.department
GROUP BY d.buildingId

SQL Query using outer join?

I have the following relations:
and I want to to list all employees that joined the company before June of 2014 but did not receive a commission in June 2014 using some kind of outer join. I came up with this query but it is not working. Could someone tell me how to query this?
SELECT DISTINCT Employee.EmpId, Employee.EmpName
FROM Employee
LEFT OUTER JOIN Commission
ON Employee.EmpId = Commission.EmpId
WHERE Employee.JoinDate BETWEEN Employee.JoinDate AND '2014-06-31'
GROUP BY Employee.EmpId, Employee.EmpName
HAVING COUNT(Commission.Commdate BETWEEN '2014-06-01' AND '2014-06-31') = 0
ORDER BY Employee.EmpId
The LEFT JOIN is a good idea. But, you want the commission dates in the ON clause. Then find the employees that do not match. So, here is a version of the query (cleaned up to use table aliases):
SELECT e.EmpId, e.EmpName
FROM Employee e LEFT OUTER JOIN
Commission c
ON e.EmpId = c.EmpId AND
c.Commdate BETWEEN '2014-06-01' AND '2014-06-31'
WHERE e.JoinDate < '2014-06-01' AND c.EmpID IS NULL
GROUP BY e.EmpId, e.EmpName
ORDER BY e.EmpId;
Perhaps a more natural way to write the query, though, is:
SELECT e.*
FROM employee e
WHERE NOT EXISTS (SELECT 1
FROM Commission c
WHERE e.EmpId = c.EmpId AND
c.Commdate BETWEEN '2014-06-01' AND '2014-06-31'
) AND
e.JoinDate < '2014-06-01';

Isa relationship query in sql

I have a disjoint relationship among my tables: Employee(empId PK, name), HourlyEmployee(empId PK FK, hourlySalary) empId is a reference to Employee.empId,
MonthlyEmployee(empId Pk FK, monthlySalary) empId is a reference to Employee.empId.
How can I create a query resulting AllEmployees(empId,name,hourlySalary,monthlySalary).
For all hourly employees monthlySalary will be null and for all monthly employess hourly salary will be null
Regards,
Tural
Use outer joins to get all employees no matter if they exist in HourlyEmployee or MonthlyEmployee (or neither of them).
select e.empid, e.name, h.hourlysalary, m.monthlysalary
from employee e
left outer join hourlyemployee h on h.empid = e.empid
left outer join monthlyemployee m on m.empid = e.empid;
select e.empid, e.name, h.hourlysalary, m.monthlysalary
from employee e
left outer join hourlyemployee h on h.empid = e.empid
left outer join monthlyemployee m on m.empid = e.empid
where (h.hourlysalary is null) or (m.monthlysalary is null);

using multiple table in SQL

I've got three tables:
department, employee and telephone
employee has columns EmpNo, Surname, Firstname and DeptNo.
telephone has columns EmpNo and Extension.
department has columns DeptNo and DeptName.
What I am trying to get is the full name, department name and telephone extension.
I think I am almost there but its not working yet.
My query
SELECT e.Firstname, e.Surname, d.DeptName, t.Extension
FROM employee AS e
INNER JOIN department AS d
INNER JOIN telephone AS t
ON e.DeptNo = d.DeptNo
ON t.EmpNo = e.EmpNo;
To fix your problem, move one of the ON clauses before the next JOIN
SELECT e.Firstname, e.Surname, d.DeptName, t.Extension
FROM employee AS e
INNER JOIN department AS d
ON e.DeptNo = d.DeptNo
INNER JOIN telephone AS t
ON t.EmpNo = e.EmpNo;
The ON clause must follow the JOIN that it is modifying.
So:
INNER JOIN department d ON e.DeptNo = d.DeptNo
and
INNER JOIN telephone t ON t.EmpNo = e.EmpNo;
Your query is wrong. Join is not in correct format. Use like below
SELECT e.Firstname, e.Surname, d.DeptName, t.Extension
FROM employee AS e
inner join department AS d
ON e.DeptNo = d.DeptNo
inner join telephone AS t
ON t.EmpNo = e.EmpNo;

SQL Server 2005 - Nested recursive query :(

I have a query that I need to execute that I do not know how to structure.
I have a table called Employees. I have another table called Company. There is a third table called Files. As you can imagine, a Company has Employees, and Employees have Files.
I need to list out all of the Employees in my database. The challenge is, I need to list the total number of Files in the same company as the Employee. I have tried variations on the following without any luck:
SELECT
e.FirstName,
e.LastName,
e.Company,
(SELECT COUNT(*) FROM Files f WHERE f.EmployeeID IN (SELECT [ID] FROM Employees e2 WHERE e2.CompanyID=e.CompanyID)) as 'FileCount'
FROM
Employees e
What am I doing wrong? Thank you!
Try this:
SELECT
e.FirstName,
e.LastName,
e.Company,
(
SELECT COUNT(*)
FROM Files f
JOIN Employees e2 ON f.EmployeeID = e2.id
WHERE e2.CompanyID = e.CompanyID
) as 'FileCount'
FROM
Employees e
There are a lot of ways to get that. If the performance is a concern, this is more optimal according to estimated execution plan costs.
SELECT
e.FirstName,
e.LastName,
e.Company,
COUNT(f.FileId)
FROM
Employees e
INNER JOIN Files f ON e.EmployeeID = f.EmployeeID
GROUP BY
e.FirstName,
e.LastName,
e.Company
A solution with no correlation in SELECT clause. Probably quicker...
SELECT
e.FirstName,
e.LastName,
e.Company,
foo.FileCount
FROM
Employees e
JOIN
(
SELECT
COUNT(*) AS FileCount, --OR COUNT(DISTINCT something) ?
e2.Company, f.EmployeeID
FROM
Files f JOIN Employees e2 ON f.EmployeeID = e2.id
GROUP BY
e2.Company, f.EmployeeID
) foo ON e.Company = foo.Company AND e.id = foo.EmployeeID
How about:
SELECT
e.FirstName,
e.LastName,
e.Company,
select count(*) from Files f, Employees e where f.EmployeeID=e.EmployeeID and e.CompanyID=emp.CompanyID
FROM
Employees emp
WITH FilesPerCompany (CompanyID, NumberOfFiles)
AS (SELECT c.ID AS CompanyID,
COUNT(*) AS NumberOfFiles
FROM Companies c
INNER JOIN Employees e ON c.ID = e.CompanyID
INNER JOIN Files f ON e.ID = f.EmployeeID
GROUP BY c.ID
)
SELECT e.FirstName,
e.LastName,
e.Company,
COALESCE(s.NumberOfFiles, 0) AS NumberOfFilesPerCompany
FROM Employees e
LEFT JOIN FilesPerCompany s
ON s.CompanyID = e.CompanyID
The following statement uses recursive joins to iterate down employees who manage other employees who manage other employees .... etc. Our structure is a little convoluted as the management structure is role based which actually allows an employee to have more than 1 manager. You can add a reference to Files within this recursion.
WITH Manager as
(SELECT c.Forenames + ' ' + c.Surname as Employee,
c2.Forenames + ' ' + c2.Surname AS Manages,
c.accountid AS AccountID, c.[Status] AS [Status]
FROM [intranet].[dbo].[tblContact] c
LEFT JOIN tblContactPost cp ON cp.contactid = c.contactid
LEFT JOIN tblPost p ON p.ParentRoleId = cp.RoleID AND p.ParentPostArea = cp.PostArea AND p.ParentPostNo = cp.PostNo
INNER JOIN tblContactPost cp2 ON cp2.RoleId = p.RoleId AND cp2.PostArea = p.PostArea AND cp2.PostNo = p.PostNo
INNER JOIN tblContact c2 ON c2.ContactID = cp2.ContactId
)
,jn AS
(SELECT Employee, Manages
FROM Manager
Where AccountID = 'ad\lgardner' AND [Status] = 'A'
UNION ALL
SELECT c.Employee, c.Manages
FROM jn as p JOIN Manager AS c
ON c.Employee = p.Manages
)
SELECT jn.Employee, jn.Manages
From jn
Order BY 1