I want one employee from every department (EmpDepartment), for example in my table there are:
3 employees with EmpDepartment 1
2 employees with EmpDepartment 2 and
1 Employee with EmpDepartment 3
I want EmployeeId, EmployeeName and EmpDepartment of any one employee from each separate department.
Use a windowing function like this:
SELECT *
FROM (
SELECT
E.*,
ROW_NUMBER() OVER (PARTITION BY EmpDepartment) AS RN
FROM Employee
) X
WHERE X.RN = 1
You can add an order clause the the windowing function if you have a business rule that you want to use in picking the employee
eg
ROW_NUMBER() OVER (PARTITION BY EmpDepartment order by EmployeeId) AS RN
This will get a random employee from each department due to ordering by NEWID()...
SELECT * FROM
(
SELECT EmployeeID, EmployeeName, EmployeeEmail
, ROW_NUMBER() OVER (PARTITION BY EmpDepartment ORDER BY NEWID()) AS rn
FROM dbo.Employee
) x
WHERE x.rn = 1
You can change the order by clause to something else if you want to.
This will return the employee from each department having the minimum EmployeeID in that department (since it is not important which employee will be in the results):
SELECT e.* FROM Employee e
WHERE NOT EXISTS (
SELECT 1 FROM Employee
WHERE EmpDepartment = e.EmpDepartment AND EmployeeID < e.EmployeeID
)
SELECT Top(1) EmployeeID, EmployeeName, EMPDeptartment FROM Employee WHERE EmpDetpartment = 1
UNION
SELECT Top(1) EmployeeID, EmployeeName, EMPDeptartment FROM Employee WHERE EmpDetpartment = 2
UNION
SELECT Top(1) EmployeeID, EmployeeName, EMPDeptartment FROM Employee WHERE EmpDetpartment = 3
You can either use rownumber to find any employee of a particular dept change rn to any value as 1,2,...etc
Select department, employee
from (
Select department, employee,
row_number() over (partition by department order by employee) rn
)
where rn =1;
or use simple group by
Select department, max(employee)
from table
group by department
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
I have this table. I want to select all employees in each profession with maximum salary.
I tried everything, but nothing seems to be working.
The below query results error.
SELECT * FROM Employee WHERE EmployeeID IN (
SELECT EmployeeID FROM Employee HAVING MAX(Salary) = Salary GROUP BY Profession)
You can use ROW_NUMBER window function
SELECT *
FROM (SELECT *,
Row_number()OVER (PARTITION BY Profession ORDER BY Salary DESC) rn
FROM Employee) a
WHERE rn = 1
Note : When there is a tie in maximum salary for a profession then this will return only one, if you need the tie records then use DENSE_RANK
SELECT *
FROM (SELECT *,
Dense_rank()OVER (PARTITION BY Profession ORDER BY Salary DESC) rn
FROM Employee) a
WHERE rn = 1
in case you want to fix your sub-query then(will return the tie records)
SELECT *
FROM Employee e1
WHERE Salary = (SELECT Max(Salary)
FROM Employee e2
WHERE e1.Profession = e2.Profession)
or
SELECT *
FROM Employee e1
WHERE EXISTS (SELECT 1
FROM Employee e2
WHERE e1.Profession = e2.Profession
HAVING Max(Salary) = e1.Salary)
SELECT *
FROM (
SELECT *
, ROW_NUMBER() OVER (PARTITION BY Profession ORDER BY Salary DESC) rn
FROM Employee
) x
WHERE x.rn = 1
Try this simple query !
SELECT
EmployeeID ,
EmployeeName ,
Profession ,
max(Salary) AS 'Salary'
FROM
Employee
GROUP BY
Profession
SELECT *
FROM employees
WHERE salary IN (SELECT MAX(salary)
FROM Employees
GROUP BY Profession)
with a as (
select a.*, row_number() over (partition by department order by attributeID) rn
from attributes a),
e as (
select employeeId, department, attribute1, 1 rn from employees union all
select employeeId, department, attribute2, 2 rn from employees union all
select employeeId, department, attribute3, 3 rn from employees
)
select e.employeeId, a.attributeid, e.department, a.attribute, a.meaning,
e.attribute1 as value
from e join a on a.department=e.department and a.rn=e.rn
order by e.employeeId, a.attributeid
this query is written by Ponder Stibbons for the answer of this question. But i am too dizzy with it as i quite don't understand what is going on here. i am new to SQL . so i would appreciate if anyone can explain what is happening on this query . thank you
Basically he unpivots the data using 3 select statements (1 for each attribute) and UNION them together to make a common table expression so that he gets rows for each employees attribute.
select employeeId, department, attribute1, 1 rn from employees union all
select employeeId, department, attribute2, 2 rn from employees union all
select employeeId, department, attribute3, 3 rn from employees
The other table he using a window function to assign a number to attribute, department. He uses this number later to join back to his unpivoted data. He posted his code for the example.
select a.*, row_number() over (partition by department order by attributeID) rn
from attributes a
I would suggest you use his example data he provided and run the following. This will show you the CTEs. I think once you see that data it will make more sense.
with a as (
select a.*, row_number() over (partition by department order by attributeID) rn
from attributes a),
e as (
select employeeId, department, attribute1, 1 rn from employees union all
select employeeId, department, attribute2, 2 rn from employees union all
select employeeId, department, attribute3, 3 rn from employees
)
SELECT * from a
SELECT * from e
Below is the table I am referring to.
I want to find ou the 2 Employees in each department with highest salary.
Further to the above answer, if there are ties (multiple employees sharing the same salary), you can use the following to bring them all through instead of just picking two at random (which is what the ROW_NUMBER clause will do)
SELECT *
FROM (
SELECT *, DENSE_RANK() OVER (PARTITION BY Dept ORDER BY Salary DESC) AS rn
FROM MyTable ) t
WHERE t.rn <= 2
Use ROW_NUMBER() to get the top salaries per Department, then select the first two records from each departmental partiton:
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Dept ORDER BY Salary DESC) AS rn
FROM MyTable ) t
WHERE t.rn <= 2
I have an Employee Table with their DeptCode. I want list of distinct DeptCode and their first created date in the Employee Table. This will also tell which employee was first entered for a specific dept in the Employee Table.
I used:
SELECT DISTINCT DEPTCODE,
CREATEDDATE
FROM EMPLOYEE
The Date Return is incorrect.
Any specific syntax to handle this issue.
Try:
SELECT DEPTCODE,
Min(CREATEDDATE)
FROM EMPLOYEE
GROUP BY DEPTCODE
If you want the department codes, earliest creation date, and the name of the employee, then I would recommend window functions:
select deptcode, name, createddate
from (select e.*,
row_number() over (partition by deptcode order by createddate) as seqnum
from employee e
) e
where seqnum = 1;
You can use GROUP BY and MIN to achieve this.
SELECT DEPTCODE, MIN(CREATEDDATE)
from EMPLOYEE
GROUP BY DEPTCODE
Something like this.
SELECT deptcode,
employee_name,
minddate
FROM employee
JOIN (SELECT deptcode,
Min(createddate) mindate
FROM employee
GROUP BY deptcode) temp
ON employee.deptcode = temp.deptcode
AND createddate = mindate