sql sub query - sql

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

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

With Join And Window Function Getting Result

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

how to find the maximum salary of employees in a specific department

I have a table named SalaryTable containing salaries of employee in various departments:
dept_id name salary
12 a 100
13 b 200
12 c 300
14 d 400
12 e 500
13 f 600
I need to find the maximum salary of each department with given department id AND the name of that person along with maximum salary.
I am using the following sql query for this
select dept_id, name, max(salary)
from SalaryTable
group by salary
But the above code is giving me error:
dept_id must be an aggregate expression or appear in GROUP BY clause
I am able to get the following table easily with this below query:
select dept_id, max(salary) as max_salary
from SalaryTable
group by salary
dept_id max_salary
12 500
13 600
14 400
but I also need the name of that person as:
REQUIRED OUTPUT
dept_id name max_salary
12 e 500
13 f 600
14 d 400
You appear to be learning SQL, so you can build on what you have. The following gets the maximum salary:
select dept_id, max(salary)
from SalaryTable
group by dept_id;
You can use this as a subquery, to get all matching names:
select st.*
from SalaryTable st join
(select dept_id, max(salary) as max_salary
from SalaryTable
group by dept_id
) std
on st.dept_id = std.dept_id and
st.salary = std.max_salary
use correlated subquery
select dept_id, name, salary
from SalaryTable a
where salary =(select max(salary) from SalaryTable b where a.dept_id=b.dept_id)
To be exact:
SELECT dept_id, NAME, salary FROM SalaryTable a
WHERE salary =(SELECT MAX(salary) FROM SalaryTable b WHERE a.dept_id=b.dept_id)
ORDER BY dept_id;
Also see try by joins because see this
Remember: Whatever you put in between select and from in single sql statement that must be used in the group by clause (That's what your error says!).
You can do it with NOT EXISTS:
select s.* from SalaryTable s
where not exists (
select 1 from SalaryTable
where dept_id = s.dept_id and salary > s.salary
)
order by s.dept_id
See the demo.
Results:
> dept_id | name | salary
> ------: | :--- | -----:
> 12 | e | 500
> 13 | f | 600
> 14 | d | 400

Select max date from joined tables with columns that has unique values

I want to get the most recent date from joined tables with unique values in 2 columns. How do I do this? I have also tried the ranking (but John has the same rank) and tried rownum = 1, but I still get the same results below for some reason
Name ID Email DeptNo DeptScore OnDate
John A46 john#doe.com 100 50 5/11/2011
John A46 johndoe#aol.com 200 75 7/21/2015
Alice B33 alice#hotmail.com 100 50 4/15/2014
I want to get the following:
Name ID Email DeptNo DeptScore OnDate
John A46 johndoe#aol.com 200 75 7/21/2015
Alice B33 alice#hotmail.com 100 50 4/15/2014
My query
select distinct e.name, e.id, e.email, d.deptno, d.deptscore, d.ondate
from
emp e
inner join dept d on
d.deptno = e.dnum
and d.ondate = e.livedate
and d.ondate = (select max(m.ondate)
from dept m
where d.ondate = m.ondate)
--where e.id in ('A46','B33')
Try to use the below Query, it will solve your problem.
select name,
id,
email,
deptno,
deptscore,
ondate
from (select e.name,
e.id,
e.email,
d.deptno,
d.deptscore,
d.ondate,
rank() over(partition by e.id,e.name order by d.ondate desc) rn
from emp e join
dept d
on d.deptno = e.dnum and d.ondate = e.livedate
) s
where rn = 1;
Output:
NAME ID EMAIL DEPTNO DEPTSCORE ONDATE
John A46 johndoe#aol.com 200 75 21-JUL-15
Alice B33 alice#hotmail.com 100 50 15-APR-14

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.