I have 2 tables employee and employeeManager.
Employee table has 3 columns:
employeeId (pk), firstname, lastname
EmployeeManager table has 5 columns:
employeemanagerid (PK),
employeeid (FK references employee > employeeid),
managerid (FK references employee > employee id),
effectivestartdate,
effectiveenddate
I need to display records as
Employeeid, firstname, lastname, isManager
The IsManager column can have 2 values: Y for yes and N for no.
I need to find the status as of today. I.E. On the day query is run.
Any help?
Presumably, you have a rule that says that a manager has people reporting to him or her. That is not the case in the real world, but it is necessary for answering your question.
You basically want an exists clause to see if anyone exists who is reporting to the manager. That looks like:
select e.*,
(case when exists (select 1
from employeemanager m
where m.managerid = e.employeeid and
m.effectivestartdate <= getdate() and
m.effectiveenddate > getdate()
)
then 'Y' else 'N'
end) as isManager
from employee e;
This subquery:
select distinct managerid
from employeemanager
where convert(date, getdate()) between effectivestartdate and effectiveenddate
returns all the managers.
Left join the table employee to that subquery and with a CASE expression get the results you need:
select e.*,
case when t.managerid is null then 'N' else 'Y' end isManager
from employee e left join (
select distinct managerid
from employeemanager
where convert(date, getdate()) between effectivestartdate and effectiveenddate
) t on t.managerid = e.employeeid
Related
I am working on a table that contains employee data. The table has historical employee records based on department and year as follows:
Now I want to consolidate records based on EmployeeId, Department and get the Min FromYear and Max ToYear like this:
I tried to use a query :
Select EmployeeId, Department, MIN(FromYear), MAX(ToYear)
from Employee
GROUP BY EmployeeId, Department
But this query fails for the employee with ID 3 as it returns me only 2 rows:
I have added a similar structure and query here: http://sqlfiddle.com/#!9/6f1e53/5
Any help would be highly appreciated!
This is a gaps-and-islands problem. Identify the islands using lag() and a cumulative sum. Then aggregate:
select employeeid, department, min(fromyear), max(toyear)
from (select e.*,
sum(case when prev_toyear >= fromyear - 1 then 0 else 1 end) over (partition by employeeid order by fromyear) as grp
from (select e.*,
lag(toyear) over (partition by employeeid, department order by fromyear) as prev_toyear
from employee e
) e
) e
group by employeeid, department, grp
order by employeeid, min(fromyear);
Here is a db<>fiddle.
you can use self join as well
select a.employeeid, min(a.fromyear), max(b.toyear) from emp a
inner join emp b on a.employeeid=b.employeeid
group by a.employeeid
DB Fiddle here
SELECT Fname,Lname
FROM EMPLOYEE
WHERE Bdate=(MaxBdate)
GROUP BY Fname,Lname
I tried it this way but does not work.
From your fiddle, assuming that supervisors have NULL in column Super_ssn, I think this will work:
SELECT FName, Lname
FROM EMPLOYEE
WHERE
Super_ssn IS NOT NULL
AND
Bdate = (SELECT MIN(Bdate) FROM EMPLOYEE
WHERE Super_ssn IS NOT NULL)
I would assume an employee (non-supervisor) is one whose ssn is not in the supervisor ssn column.
The oldest can be derived from the min windowing function.
with employees_only as (
select e.*, min (bdate) over (partition by 1) as min_bdate
from employee e
where not exists (
select null
from employee s
where s.super_ssn = e.ssn
)
)
select fname, lname
from employees_only
where bdate = min_bdate
I'm trying to write some SQL that queries two tables and brings back records that doesn't have a particular type of record in the other table.
If table 1 is an employee table that has EmpID, name, surname.
and the 2nd table is a bookings table that has Booking ID, EmpID, year
I want to find all records where there are no bookings for 2014.
so if the employee table is:
EMPID Name Surname
1 John Doe
2 Bob Smith
and the Booking table is
Booking ID Emp ID Year
1 1 2013
2 1 2014
3 2 2012
4 2 2013
I want the sql to only
SELECT * FROM employee
LEFT JOIN Booking ON Booking.empid = employee.empid AND year = 2014
WHERE Booking.empid IS NULL
Add a WHERE clause with a NOT EXISTS check to filter the records you require:
SELECT e.EMPID, e.[Name], e.Surname
FROM Employee e
WHERE NOT EXISTS
(SELECT EmpID
FROM Booking b
WHERE b.BookingId = e.EmpId and b.Year = 2014)
Sample SQL Fiddle
For reference, here's the SQL Fiddle create / insert script:
create table employee(EMPID int, Name varchar(50), Surname varchar(50))
create table booking(BookingID int, EmpID int, Year int)
insert into employee (EMPID, Name, Surname) values(1,'John','Doe')
insert into employee (EMPID, Name, Surname) values(2,'Bob','Smith')
insert into booking(BookingID,EmpID,Year) values(1,1,2013)
insert into booking(BookingID,EmpID,Year) values(2,1,2014)
insert into booking(BookingID,EmpID,Year) values(3,2,2012)
insert into booking(BookingID,EmpID,Year) values(4,2,2013)
One often over looked solution is EXCEPT. This is SQL server specific syntax and is basically the opposite of a UNION
SELECT
e.EMPID,
e.Name,
e.Surname
FROM
employee e
EXCEPT
SELECT
e.EMPID,
e.Name,
e.Surname
FROM
employee e
INNER JOIN Booking B
ON e.empID = b.empid
WHERE
b.year = 2014
DEMO
Another also overlooked syntax is != ANY the major difference between that and NOT IN is that you don't have to worry about null empId in booking
SELECT
EmpId, Name
FROM employee e
WHERE empid != ANY (SELECT empid
FROM booking
WHERE year = 2014)
DEMO
select * from employee
where empid not in
(select empid from Booking
where year = 2014)
Illustrative only, of course, "select *" generally isn't a good thing, better to return the columns you specifically want...
If your Booking table contains null EmpIds, however, you could cater for it with something like this:
select * from employee
where empid not in
(select empid from Booking
where year = 2014 and empid is not null)
I have a sql table called Employee in which I have EmployeeID, Status and DepartmentID columns. Now I have been assigned with the task of creating a tabular report where in I need count of total employees for a department, count of Employees which are active(Status), and DepartmentID.
Getting the Count of total employees and corresponding DepartmentID is simple with a Group By clause.
Select count(*) as 'Total Employees',DepartmentID from Employees
Group By DepartmentID
How would I get the Count of Employees with a particular Status for the same DepartmentID as the outer query?
Please let me know if you want some more clarifications about the problem.
If you have column Status with values active , no need of outer query
Select count(*) as 'Total Employees',
SUM(CASE WHEN status='Active' THEN 1 ELSE 0 END ) as TotalActiveEmployees,
DepartmentID
from Employees
Group By DepartmentID
Try this one.
Select count(*) as 'Total Employees',
COUNT(CASE WHEN status='Active' THEN 1 ELSE 0 END ) as TotalActiveEmployees,
DepartmentID
from Employees
Group By DepartmentID
I have a table that contains an employeeID and an SSN field. I am trying to filter out all records with the following critera:
All employees that have a single SSN entry who's value is null
All employees that have greater than one SSN entry
The following shows the three scenarios
ID SSN
1 000000000
1 NULL
ID SSN
1 000000000
1 111111111
ID SSN
1 NULL
Here is the table definition: I am populating this table withe data from a Sybase Data base
http://tinypic.com/r/65wvhi/6
Thanks,
Brad
select employeeID
from YourTable
group by
employeeID
having count(case when SSN is null then 1 end) > 0
or count(distinct SSN) > 1
You would use aggregation for this, with a having clause:
select e.id
from ssns e
group by e.id
having (count(*) = 1 and count(ssn) = 0) or -- first condition
count(*) > 1 -- second condition