With Join And Window Function Getting Result - sql

A Table Dept
Id Salary Dept
1 1000 A
2 2000 B
3 5000 A
4 2500 C
5 3000 D
So the Output
Id Salary Dept
1 6000 A
Need To Get the Sum of Salary and Which department as the max salary using Join or Window function

You seem to want:
select d.dept, sum(d.salary)
from dept d
group by d.dept
order by max(d.salary) desc
fetch first 1 row only

If you are using MSSQL you can try this
select top 1 d.Dept, Sum(d.Salary) as Salary from Dept d group by d.Dept order by Sum(d.Salary) desc

Related

Write a SQL query to find employees who earn the top three salaries for the IT department

Write a SQL query to find employees who earn the top three salaries for the IT department.
My query:
SELECT TOP(3) WITH TIES
d.name AS department, e.name AS employee, e.salary
FROM
employee e, department d
WHERE
e.departmentid = d.id AND d.name ='IT'
ORDER BY
e.salary DESC
This is supposed to show me 4 results. Because I'm including the ties. But for some reason it is not. I don't understand why. I need the top 3 salaries including the ties.
I get this result:
Department
Employee
Salary
IT
Max
90000
IT
Randy
85000
IT
Joe
85000
Expected results:
Department
Employee
Salary
IT
Max
90000
IT
Randy
85000
IT
Joe
85000
IT
Will
70000
Employee table
Id
Name
Salary
DepartmentId
1
Joe
85000
1
2
Henry
80000
2
3
Sam
60000
2
4
Max
90000
1
5
Janet
69000
1
6
Randy
85000
1
7
Will
70000
1
Department table:
Id
Name
1
IT
2
Sales
You are going to need window functions for this. SELECT TOP (n) WITH TIES stops at row n and only includes more rows if there are ties.
So, in addition to proper, explicit, standard, readable JOIN syntax, you can learn about window functions:
SELECT e.*
FROM (SELECT d.name as department, e.name as employee, e.salary,
DENSE_RANK() OVER (ORDER BY e.salary DESC) as seqnum
FROM employee e JOIN
department d
ON e.departmentid = d.id and d.name = 'IT'
) e
WHERE seqnum <= 3
ORDER BY e.salary DESC

Removing duplicates by adding them up [SQL]

I have a query like this:
select employee_id, salary
from salary
left join employee on salary.employee_id=employee.id_employee;
It returns me these results
EMPLOYEE ID | SALARY
-------------|-------
1 | 50
2 | 50
3 | 50
1 | 30
How do I remove duplicates by adding them up, like this:
EMPLOYEE ID | SALARY
------------|--------
1 | 80
2 | 50
3 | 50
There is no reason for a left join from salary to employee. Presumably, every employee_id in salary refers to a valid employee. So, this should do what you want:
select s.employee_id, sum(s.salary) as salary
from salary s
group by s.employee_id;
If you want all employees, even those who are not in the salary table, then an outer join is appropriate -- but employee should be first:
select e.id_employee, sum(s.salary) as salary
from employee e left join
salary s
on s.employee_id = e.id_employee
group by e.id_employee;
Employees not in salary will have a value of NULL.
Note that the group by condition in this query is on employee, the first table in the left join.
select employee_id, SUM(salary) as salary
from salary
left join employee on salary.employee_id=employee.id_employee
group by emplyee_id;
This is exactly what a group by clause is for. You'll have to group by the emplopyee_id and specify how you want to aggregate the salary:
SELECT employee_id, SUM(salary)
FROM salary
GROUP BY employee_id

ORA-00923: FROM keyword not found where expected (Retrieve department wise highest 2 salaries)

I was trying to retrieve the highest two salaries by each department. But I am getting error! Please help, I will be appreciated, Thanks.
CREATE TABLE emp_h ( Dept varchar(100), Emp varchar(100), Sal numeric(18,2) )
Values are inserted in this table below.
SELECT * FROM emp_h
DEPT EMP SAL
Comp A 6000
Comp B 7000
Comp C 10000
Comp D 9000
Elec P 2000
Elec Q 10000
Elec R 11000
Eng AA 15000
Eng BB 2000
Eng BB 7000
Eng BB 3000
I want the output (Department wise top 2 highest salary)
Dept Emp Sal
----------------------------
Comp C 10000
Comp D 9000
Elec R 11000
Elec Q 10000
Eng AA 15000
Eng BB 7000
Now I ran this query to retrieve the highest 2 salary each department wise:
SELECT * FROM(SELECT RANK() OVER (PARTITION BY DEPT ORDER BY SAL DESC) AS 'Rank', * FROM emp_h) AS A WHERE RANK <= 2
Result:
ORA-00923: FROM keyword not found where expected
00923. 00000 - "FROM keyword not found where expected"
*Cause:
*Action:
Error at Line: 25 Column: 61
Oracle likes you to qualify * if there are any other columns on the row. So try this:
SELECT e.*
FROM (SELECT RANK() OVER (PARTITION BY DEPT ORDER BY SAL DESC) AS rnk, e.*
FROM emp_h e
) e
WHERE rnk <= 2;

select dept names who have more than 2 employees whose salary is greater than 1000

How would do the following in SQL
"select dept names who have more than 2 employees whose salary is greater than 1000" ?
DeptId DeptName
------ --------
1 one
2 two
3 three
EmpId DeptId Salary
----- ------ ------
121 1 2000
122 1 2000
123 1 5000
124 1 4000
131 2 2000
132 2 6000
133 2 1000
134 2 1000
125 3 1000
126 3 20000
RESULT: one
How about something like this?
SELECT D.DeptName FROM
Department D WHERE (SELECT COUNT(*)
FROM Employee E
WHERE E.DeptID = D.DeptID AND
E.Salary > 1000) > 2
SELECT DEPTNAME
FROM(SELECT D.DEPTNAME,COUNT(EMPID) AS TOTEMP
FROM DEPT AS D,EMPLOYEE AS E
WHERE D.DEPTID=E.DEPTID AND SALARY>1000
GROUP BY D.DEPTID
)
WHERE TOTEMP>2;
select min(DEPARTMENT.DeptName) as deptname
from DEPARTMENT
inner join employee on
DEPARTMENT.DeptId = employee.DeptId
where Salary > 1000
group by (EmpId) having count(EmpId) > =2
hope this helps
select DeptName from DEPARTMENT inner join EMPLOYEE using (DeptId) where Salary>1000 group by DeptName having count(*)>2
select D.DeptName from [Department] D where D.DeptID in
(
select E.DeptId from [Employee] E
where E.Salary > 1000
group by E.DeptId
having count(*) > 2
)
select deptname from dept_1
where exists
(
SELECT DeptId,COUNT(*)
FROM emp_1
where salary>1000
and emp_1.deptid=dept_1.deptid
GROUP BY DeptId
having count(*)>2)
1:list name of all employee who earn more than RS.100000 in a year.
2:give the name of employee who earn heads the department where employee with employee I.D
My main advice would be to steer clear of the HAVING clause (see below):
WITH HighEarners AS
( SELECT EmpId, DeptId
FROM EMPLOYEE
WHERE Salary > 1000 ),
DeptmentHighEarnerTallies AS
( SELECT DeptId, COUNT(*) AS HighEarnerTally
FROM HighEarners
GROUP
BY DeptId )
SELECT DeptName
FROM DEPARTMENT NATURAL JOIN DeptmentHighEarnerTallies
WHERE HighEarnerTally > 2;
The very early SQL implementations lacked derived tables and HAVING was a workaround for one of its most obvious drawbacks (how to select on the result of a set function from the SELECT clause). Once derived tables had become a thing, the need for HAVING went away. Sadly, HAVING itself didn't go away (and never will) because nothing is ever removed from standard SQL. There is no need to learn HAVING and I encourage fledgling coders to avoid using this historical hangover.

sql sub query

Hi I need a small help regarding writing a simple query. I want to display results based on max number of employees in a dept.
Here is my table
empid dept sal
emp001 d001 10000
emp002 d001 10000
emp003 d002 20000
emp004 d001 10000
emp005 d003 5000
emp006 d003 5000
Expected result
empid dept sal
emp001 d001 10000
emp002 d001 10000
emp004 d001 10000
emp005 d003 5000
emp006 d003 5000
emp003 d002 20000
so dept1 contains 3 employees so it should come first and dept3 contains 2 employees so it will come next and so on
Thanks in advance,
Nagu
The answer hardly depends on your DBMS !
With Oracle 8+ you can use analytic functions :
select empid, dept, sal
from MyTable
order by count(empid) over (partition by dept) desc
Just tried this in MySQL, and with this query:
SELECT e1. * , count( e2.empid ) AS c
FROM employees e1 LEFT JOIN
employees e2 ON e1.dept = e2.dept
GROUP BY e1.empid ORDER BY c DESC
I got this result:
empid dept sal c
emp001 d001 10000 3
emp004 d001 10000 3
emp002 d001 10000 3
emp006 d003 5000 2
emp005 d003 5000 2
emp003 d002 20000 1
And then you could of course sort on empid to get the emp002 before the emp004 etc :)
Edit: A better MySQL query would be with not selecting * elements and escaping all table and field names with backticks, something like this:
SELECT `e1`.`empid`, `e1`.`dept`,
`e1`.`sal`, COUNT(`e2`.`empid`) AS `c`
FROM `employees` `e1` LEFT JOIN
`employees` `e2` ON `e1`.`dept` =
`e2`.`dept` GROUP BY `e1`.`empid`
ORDER BY `c` DESC, `e1`.`empid`
You could calculate the headcount per department in a join, and then order by that:
select e.empid, e.dept e.sal
from employees e
inner join (
select dept, total = count(*)
from employees
group by dept
) headcount hc on hc.dept = e.dept
order by hc.total desc, e.dept, e.sal
I don't have a database avaiable to test this on, but try giving this a whirl:
SELECT empid, dept, sal
FROM emp_table
JOIN
(SELECT COUNT(empid) [emp_count], dept
FROM emp_table
GROUP BY dept
) count_table
ON emp_table.dept = count_table.dept
ORDER BY
emp_count DESC
, empid ASC
Version without CTE:
Select e.empid, e.dept e.sal
From employees e
Inner Join ( Select dept, count(empid) as cnt
from employees
group by dept
) c on e.dept=c.dept
Order By c.cnt DESC, e.empid ASC
The answer hardly depends on your DBMS ! With Oracle 8+ you can use analytic functions :
The same query works with SQL Server 2005+
There is another solution that gives same result and almost the same execution plan:
;With DeptCount as
( Select dept, count(empid) as cnt
from employees
group by dept
)
Select e.empid, e.dept e.sal
From employees e
Inner Join DeptCount c
on e.dept=c.dept
Order By c.cnt DESC, e.empid ASC
I am not sure what you want exactly, but this query gives you the number of employees per dept.
SELECT dept, COUNT(*) FROM table GROUP BY dept
Best Regards