i have two tables
employee :
employee_number employee_name salary divison_id
division :
division_id division_name
How to Show division id, division name, number of employees working in each division that has the highest number of employees.
I want to have an outcome like this :
division_id division_name total_employee
Z-100 | finance | 3
SELECT *
FROM (SELECT e.division_id,
d.division_name,
Count(1) total_employee
FROM employee e
JOIN division d
ON e.division_id = d.division_id
GROUP BY e.division_id
ORDER BY Count(1) DESC)a
LIMIT 1
If you want all the department with most employees you should consider that more than one department can have that. So I am revising my answer and instead of top I am using Rank() with CTE to get all the divisions with most number of employees.
with DivisionWithMostEmployee as
(
select Rank()over(order by count(*) desc) RowNumber, d.division_id, d.division_name, count(*) TotalEmployee
from division d, employee e where d.division_id=e.division_id
group by d.division_id,d.division_name
)
select Division_id,Division_name,TotalEmployee from DivisionWithMostEmployee where RowNumber=1
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
Having two tables
Employee
Id
Name
Salary
DepartmentId
and
Departament
Id
Name
How can I get the highest average salary within two tables
like
Joe and Max belong to dept 1 so, avg is (70K+90K)/2
= 80K
and
Henry and Sam belog to dept 2, avg is (80K + 60K)/2=70k
so How to select the greatest avg salary by depto?, in this case
IT 80K
i have been trying:
'group the salary by each department and use the Max function to obtain the highest one.
select
Department.Name as Department,
T.M as Salary
from
Employee,
Department,
(select DepartmentId as ID, Max(Salary) as M from Employee group by DepartmentId) as T
where
Employee.Salary = T.M and
Department.Id = T.ID and
Employee.DepartmentId = Department.Id
enter image description here
If multiple department having same maximum avg salary then this solution will return multiple rows.
SELECT *
FROM(
SELECT d.Id, d.Name, AVG(e.Salary) avg_salary, RANK() OVER(ORDER BY AVG(e.Salary) DESC) AS rank_
FROM Employee e
INNER JOIN Departament d ON e.DepartmentId = d.Id
GROUP BY d.Id, d.Name
)T
WHERE rank_ = 1
If you want to get the average just for the department, you can use in this way.
select DepartmentId as ID, de.name as Deptname, Avg(Salary) as M from Employee em1
join Department de on de.departmentID = em1.DepartmentId
group by DepartmentId, de.name
If you want employee name along with highest average then you can use this approach as well.
select
Deptname as Department,
e.Name as Employeename,
z.M as Salary
from
Employee e
join
( select DepartmentId,Deptname, M, row_number() (order by m desc) rownum from ( select DepartmentId as ID, de.name as Deptname, Avg(Salary) as M from Employee em1
join Department de on de.departmentID = em1.DepartmentId
group by DepartmentId, de.name) as T) z
on
e.DepartmentId = T.DepartmentId and z.rownum = 1
If you want a full answer, you should provide DDL, sample data and desired result.
If I understand you correctly, you are looking for something like:
SELECT DepartmentID, AVG(Salary) AS AverageSalaryForDept
FROM Employee
GROUP BY DepartmentID
ORDER BY AverageSalaryForDept DESC;
This will give you all the averages, ordered from the highest to the lowest. Now if you want just the top one, add a FETCH clause:
SELECT DepartmentID, AVG(Salary) AS AverageSalaryForDept
FROM Employee
GROUP BY DepartmentID
ORDER BY AverageSalaryForDept DESC
OFFSET 0 ROWS FETCH NEXT 1 ROW ONLY;
HTH
Tables:
Department (dept_id,dept_name)
Students(student_id,student_name,dept_id)
I am using Oracle. I have to print the name of that department that has the minimum no. of students. Since I am new to SQL, I am stuck on this problem. So far, I have done this:
select d.department_id,d.department_name,
from Department d
join Student s on s.department_id=d.department_id
where rownum between 1 and 3
group by d.department_id,d.department_name
order by count(s.student_id) asc;
The output is incorrect. It is coming as IT,SE,CSE whereas the output should be IT,CSE,SE! Is my query right? Or is there something missing in my query?
What am I doing wrong?
One of the possibilities:
select dept_id, dept_name
from (
select dept_id, dept_name,
rank() over (order by cnt nulls first) rn
from department
left join (select dept_id, count(1) cnt
from students
group by dept_id) using (dept_id) )
where rn = 1
Group data from table students at first, join table department, rank numbers, take first row(s).
left join are used is used to guarantee that we will check departments without students.
rank() is used in case that there are two or more departments with minimal number of students.
To find the department(s) with the minimum number of students, you'll have to count per department ID and then take the ID(s) with the minimum count.
As of Oracle 12c this is simply:
select department_id
from student
group by department_id
order by count(*)
fetch first row with ties
You then select the departments with an ID in the found set.
select * from department where id in (<above query>);
In older versions you could use RANK instead to rank the departments by count:
select department_id, rank() over (order by count(*)) as rnk
from student
group by department_id
The rows with rnk = 1 would be the department IDs with the lowest count. So you could select the departments with:
select * from department where (id, 1) in (<above query>);
I'm trying to increase the salary for those employees who treat at least 2 patients by 10%. My problem is that the salary first multiplies by 2 for every patient they treat and then multiplies by 10% at the end. For exampel if the employee earns 25.000 and treats 3 people the new salary becomes 82.500.
select distinct t.empNbr, e.Salary, sum(e.Salary*1.1) as NewSalary from Treats t
inner join Employee e
on e.empNbr=t.empNbr
WHERE t.empNbr IN
(
SELECT empNbr
FROM Treats
GROUP BY empNbr
HAVING COUNT(*) >= 2)
group by t.empNbr, e.Salary
CROSS APPLY should help:
SELECT e.empNbr,
e.Salary,
e.Salary*1.1 as NewSalary
FROM Employee e
CROSS APPLY (
SELECT empNbr
FROM Treats
WHERE e.empNbr = empNbr
GROUP BY empNbr
HAVING COUNT(*) > 1
) as t
The t part gets empNbr we need. Then we select empNbr and salary from Employee table and do math :)
One more way:
SELECT TOP 1 WITH TIES
e.empNbr,
e.Salary,
e.Salary*1.1 as NewSalary
FROM Employee e
INNER JOIN Treats t
ON e.empNbr = t.empNbr
ORDER BY
CASE WHEN COUNT(t.empNbr) OVER (PARTITION BY t.empNbr ORDER BY t.empNbr) > 1 THEN 1 ELSE 0 END DESC,
ROW_NUMBER() OVER (PARTITION BY t.empNbr ORDER BY t.empNbr)
This should be the right query. Let me know if this works
select empNbr, Salary, sum(Salary*1.1) as NewSalary
from employee
where empNbr in (select empNbr
from Treats
group by empNbr
having count(*) >=2) ----- Ordered as a code
Christopher, You can use below query to get the result,
SELECT t.empNbr,
e.Salary,
(e.Salary * e.count +(e.Salary/10) ) as NewSalary
from Treats t
INNER JOIN
(SELECT empNbr, COUNT(*) AS count Employee GROUP BY empNbr) e
ON e.empNbr=t.empNbr
AND e.count >=2
Explination
1. We can calculate result without having clause2.In the inner join, empNbr and the count of that employee in derived3.Using this count in the select query, the current salary is multiplied and 10% is added with the salary
Hope this is what you need. Any issues, feel free to ask
This is my database:
Table Country: id integer (pk), varchar name,
Table Employe: id integer (pk), countryid integer(fk), varchar name, integer salary.
I want to display employees with the highest salary in every country, but I can display only one employer with the highest salary.
This is my SQL query:
Select *
from Employe
order by Employe.salary
desc LIMIT 1;
In Postgres you can use the comfortable distinct on:
select distinct on (c.name) c.name country, e.name employe, salary
from employe e
join countries c on c.id = e.country_id
order by c.name, salary desc
Try this query
SELECT Employe.countryid , Max(Employe.salary) from Employe GROUP BY Employe.countryid
You could use the rank window function to get the "first" employee[s] (salary-wise) per country:
SELECT id, c.name, e.name, salary
FROM (SELECT id, countryid, name, salary,
RANK() OVER (PARTITION BY countryid ORDER BY salary DESC) rk
FROM employee) e
JOIN country c ON c.id = e.countryid
WHERE rk = 1