Using the MIN function in the having clause - sql

I want to get the name of the employee who has the minimum salary. Is there a way to do this using only one query? I have given my query below, it doesn't work because the having clause requires a condition. Is there any way to give a condition in the having clause that will retreive the employee name with the minimum salary?
SELECT first_name,min(salary) as "sal"
FROM Employees
GROUP BY first_name
having min(salary);

How about using ROWNUM?
SELECT *
FROM(SELECT first_name, salary
FROM Employees
ORDER BY salary
) WHERE ROWNUM = 1

SELECT first_name, salary as "sal"
FROM employees
WHERE salary =(SELECT MIN(salary)
FROM employees);

Try this solution, inspired from here:
SELECT e1.first_name, e1.salary AS "sal"
FROM Employees e1
LEFT OUTER JOIN Employees e2
ON (e1.id <> e2.id AND e1.salary > e2.salary)
WHERE e2.id IS NULL;

With a single SELECT statement:
SELECT MIN( first_name ) KEEP ( DENSE_RANK FIRST ORDER BY salary ASC, first_name ASC ) AS first_name,
MIN( salary ) KEEP ( DENSE_RANK FIRST ORDER BY salary ASC, first_name ASC ) AS salary
FROM Employees;
SQLFIDDLE
However, if there are multiple people with the same minimum salary then this will only get the one with the name which is first alphabetically.
You can get all the names, but it does require multiple SELECT statements:
SELECT first_name, salary
FROM Employees
WHERE salary = ( SELECT MIN(salary) FROM Employees );
But having multiple SELECT statements isn't a bad thing.
SQLFIDDLE

SELECT TOP 1 WITH TIES *
FROM employees
ORDER BY salary ASC

If you need the employee with the lowest salary why don't you use Order By ..
SELECT top 1 first_name,min(salary) as LowestSalary
FROM Employees order by Salary asc

SELECT first_name,min(salary) as "sal"
FROM Employees
GROUP BY first_name
having min(salary) >0;

If you want to do this with only one query, while also retrieving all employees with the minimum salary (example: you have a minimum salary of $40,000, but two employees have this exact salary) you could join the table with itself. This solution also uses the 'having' clause that you included in your original question.
SELECT e.first_name,e.salary AS "sal"
FROM Employees e, Employees e2
GROUP BY first_name
HAVING MIN(e2.salary)=e.salary;

Related

Retrieve the names of employees who is making least in their departments

I have two tables
EMPLOYEE (Fname, Lname, Ssn, Salary, Dno)
DEPARTMENT (Dname, Dno, Location)
I want to list the names of all employees making the least in their department
I have come up with this
select min(E.Salary) from EMPLOYEE E group by E.Dno;
but how do I join the EMPLOYEE table with it and display the 'Fname' and 'Lname';
Analytic functions would be best but this would also work:
select *
from employee e
where salary = (select min(x.salary) from employee x where x.dno = e.dno)
Use Analytic function, ROW_NUMBER() OVER( PARTITION BY DNO ORDER BY SALARY) as RN. So, WHERE RN = 1 will give you the employee with least salary in each department.
Remember, if there are two employees with same salary, then you need to use DENSE_RANK to avoid similar rank.
Note : This answer is for Oracle.
A simple way to do it is to check that no one with a lower salary exists in the same department;
SELECT e1.*
FROM employee e1
WHERE NOT EXISTS(
SELECT 1 FROM employee e2 WHERE e1.dno = e2.dno AND e1.salary > e2.salary
);
An SQLfiddle to test with.

How to write an SQL query for this scenario?

I have a table containing attributes Id, Emp_name, dept_name, salary. Now i want to write an SQL query that will give me the dept_name value for which the overall salary of all employees belonging to that department is the highest, i.e dept for which sum of salaries of all its employees is the highest...? If there is any similar question with answer on stackoverflow, please suggest.. I dint find one. Thanks :)
I tried group by with sum() function, but i could not get how to find the maximum and compare it with sum.
Can you do
SELECT TOP 1 dept_name FROM table GROUP BY dept_name ORDER BY SUM(salary) DESC
Seems like a textbook example for GROUP BY:
select dept_name, total_salary from (
Select dept_name, sum(salary) as total_salary
from my_table
group by dept_name
) order by total_salary desc
try this:
select top 1 dept_name from myTable group by dept_name order by sum(salary) desc
SELECT dept_name FROM table
GROUP BY dept_name
ORDER BY SUM(salary) DESC
LIMIT 1
And you would also better have you departments in another table linked to the first table via foregn keys. Just a note.
I don't know exactly know your requirements, but perhaps there is another point to be considered: Two (or more) departments could have the same sum of salary.
I have not tested the query, but this should give you all departments which have the maximum some of salary:
select dept_name FROM table_name GROUP BY dept_name HAVING SUM(salary)=(select MAX(sum_salary) FROM (select SUM(salary) AS sum_salary FROM table_name GROUP BY dept_name))

How to get second-highest salary employees in a table

It's a question I got this afternoon:
There a table contains ID, Name, and Salary of Employees, get names of the second-highest salary employees, in SQL Server
Here's my answer, I just wrote it in paper and not sure that it's perfectly valid, but it seems to work:
SELECT Name FROM Employees WHERE Salary =
( SELECT DISTINCT TOP (1) Salary FROM Employees WHERE Salary NOT IN
(SELECT DISTINCT TOP (1) Salary FROM Employees ORDER BY Salary DESCENDING)
ORDER BY Salary DESCENDING)
I think it's ugly, but it's the only solution come to my mind.
Can you suggest me a better query?
Thank you very much.
To get the names of the employees with the 2nd highest distinct salary amount you can use.
;WITH T AS
(
SELECT *,
DENSE_RANK() OVER (ORDER BY Salary Desc) AS Rnk
FROM Employees
)
SELECT Name
FROM T
WHERE Rnk=2;
If Salary is indexed the following may well be more efficient though especially if there are many employees.
SELECT Name
FROM Employees
WHERE Salary = (SELECT MIN(Salary)
FROM (SELECT DISTINCT TOP (2) Salary
FROM Employees
ORDER BY Salary DESC) T);
Test Script
CREATE TABLE Employees
(
Name VARCHAR(50),
Salary FLOAT
)
INSERT INTO Employees
SELECT TOP 1000000 s1.name,
abs(checksum(newid()))
FROM sysobjects s1,
sysobjects s2
CREATE NONCLUSTERED INDEX ix
ON Employees(Salary)
SELECT Name
FROM Employees
WHERE Salary = (SELECT MIN(Salary)
FROM (SELECT DISTINCT TOP (2) Salary
FROM Employees
ORDER BY Salary DESC) T);
WITH T
AS (SELECT *,
DENSE_RANK() OVER (ORDER BY Salary DESC) AS Rnk
FROM Employees)
SELECT Name
FROM T
WHERE Rnk = 2;
SELECT Name
FROM Employees
WHERE Salary = (SELECT DISTINCT TOP (1) Salary
FROM Employees
WHERE Salary NOT IN (SELECT DISTINCT TOP (1) Salary
FROM Employees
ORDER BY Salary DESC)
ORDER BY Salary DESC)
SELECT Name
FROM Employees
WHERE Salary = (SELECT TOP 1 Salary
FROM (SELECT TOP 2 Salary
FROM Employees
ORDER BY Salary DESC) sel
ORDER BY Salary ASC)
SELECT * from Employee
WHERE Salary IN (SELECT MAX(Salary)
FROM Employee
WHERE Salary NOT IN (SELECT MAX(Salary)
FFROM employee));
Try like this..
This might help you
SELECT
MIN(SALARY)
FROM
EMP
WHERE
SALARY in (SELECT
DISTINCT TOP 2 SALARY
FROM
EMP
ORDER BY
SALARY DESC
)
We can find any nth highest salary by putting n (where n > 0) in place of 2
Example for 5th highest salary we put n = 5
How about a CTE?
;WITH Salaries AS
(
SELECT Name, Salary,
DENSE_RANK() OVER(ORDER BY Salary DESC) AS 'SalaryRank'
FROM
dbo.Employees
)
SELECT Name, Salary
FROM Salaries
WHERE SalaryRank = 2
DENSE_RANK() will give you all the employees who have the second highest salary - no matter how many employees have the (identical) highest salary.
All of the following queries work for MySQL:
SELECT MAX(salary) FROM Employee WHERE Salary NOT IN (SELECT Max(Salary) FROM Employee);
SELECT MAX(Salary) From Employee WHERE Salary < (SELECT Max(Salary) FROM Employee);
SELECT Salary FROM Employee ORDER BY Salary DESC LIMIT 1 OFFSET 1;
SELECT Salary FROM (SELECT Salary FROM Employee ORDER BY Salary DESC LIMIT 2) AS Emp ORDER BY Salary LIMIT 1;
Another intuitive way is :-
Suppose we want to find Nth highest salary then
1) Sort Employee as per descending order of salary
2) Take first N records using rownum. So in this step Nth record here is Nth highest salary
3) Now sort this temporary result in ascending order. Thus Nth highest salary is now first record
4) Get first record from this temporary result.
It will be Nth highest salary.
select * from
(select * from
(select * from
(select * from emp order by sal desc)
where rownum<=:N )
order by sal )
where rownum=1;
In case there are repeating salaries then in innermost query distinct can be used.
select * from
(select * from
(select * from
(select distinct(sal) from emp order by 1 desc)
where rownum<=:N )
order by sal )
where rownum=1;
select MAX(Salary) from Employee WHERE Salary NOT IN (select MAX(Salary) from Employee );
Simple way WITHOUT using any special feature specific to Oracle, MySQL etc.
Suppose EMPLOYEE table has data as below. Salaries can be repeated.
By manual analysis we can decide ranks as follows :-
Same result can be achieved by query
select *
from (
select tout.sal, id, (select count(*) +1 from (select distinct(sal) distsal from
EMPLOYEE ) where distsal >tout.sal) as rank from EMPLOYEE tout
) result
order by rank
First we find out distinct salaries.
Then we find out count of distinct salaries greater than each row.
This is nothing but the rank of that id.
For highest salary, this count will be zero. So '+1' is done to start rank from 1.
Now we can get IDs at Nth rank by adding where clause to above query.
select *
from (
select tout.sal, id, (select count(*) +1 from (select distinct(sal) distsal from
EMPLOYEE ) where distsal >tout.sal) as rank from EMPLOYEE tout
) result
where rank = N;
The simple way is to use OFFSET. Not only second, any position we can query using offset.
SELECT SALARY,NAME FROM EMPLOYEE ORDER BY SALARY DESC LIMIT 1 OFFSET 1 --Second largest
SELECT SALARY,NAME FROM EMPLOYEE ORDER BY SALARY DESC LIMIT 1 OFFSET 9 --For 10th largest
I think you would want to use DENSE_RANK as you don't know how many employees have the same salary and you did say you wanted nameS of employees.
CREATE TABLE #Test
(
Id INT,
Name NVARCHAR(12),
Salary MONEY
)
SELECT x.Name, x.Salary
FROM
(
SELECT Name, Salary, DENSE_RANK() OVER (ORDER BY Salary DESC) as Rnk
FROM #Test
) x
WHERE x.Rnk = 2
ROW_NUMBER would give you unique numbering even if the salaries tied, and plain RANK would not give you a '2' as a rank if you had multiple people tying for highest salary. I've corrected this as DENSE_RANK does the best job for this.
Below query can be used to find the nth maximum value, just replace 2 from nth number
select * from emp e1 where 2 =(select count(distinct(salary)) from emp e2
where e2.emp >= e1.emp)
Here I used two queries for the following scenarios which are asked during an interview
First scenario:
Find all second highest salary in the table (Second highest salary with more than
one employee )
select * from emp where salary
In (select MAX(salary) from emp where salary NOT IN (Select MAX(salary) from
emp));
Second scenario:
Find only the second highest salary in the table
select min(temp.salary) from (select * from emp order by salary desc limit 2)
temp;
There are two way to do this first:
Use subquery to find the 2nd highest
SELECT MAX(salary) FROM employees
WHERE salary NOT IN (
SELECT MAX (salary) FROM employees)
But this solution is not much good as if you need to find out the 10 or 100th highest then you may be in trouble. So instead go for window function like
select * from
(
select salary,ROW_NUMBER() over(
order by Salary desc) as
rownum from employees
) as t where t.rownum=2
By using this method you can find out nth highest salary without any trouble.
select * from emp where salary = (
select salary from
(select ROW_NUMBER() over (order by salary) as 'rownum', *
from emp) t -- Order employees according to salary
where rownum = 2 -- Get the second highest salary
)
select max(age) from yd where age<(select max(age) from HK) ; /// True two table Highest
SELECT * FROM HK E1 WHERE 1 =(SELECT COUNT(DISTINCT age) FROM HK E2 WHERE E1.age < E2.age); ///Second Hightest age RT single table
select age from hk e1 where (3-1) = (select count(distinct (e2.age)) from yd e2 where e2.age>e1.age);//// same True Second Hight age RT two table
select max(age) from YD where age not in (select max(age) from YD); //second hight age in single table
Can we also use
select e2.max(sal), e2.name
from emp e2
where (e2.sal <(Select max (Salary) from empo el))
group by e2.name
Please let me know what is wrong with this approach
SELECT *
FROM TABLE1 AS A
WHERE NTH HIGHEST NO.(SELECT COUNT(ATTRIBUTE) FROM TABLE1 AS B) WHERE B.ATTRIBUTE=A.ATTRIBUTE;
this is the simple query .. if u want the second minimum then just change the max to min and change the less than(<) sign to grater than(>).
select max(column_name) from table_name where column_name<(select max(column_name) from table_name)
SELECT name
FROM employee
WHERE salary =
(SELECT MIN(salary)
FROM (SELECT TOP (2) salary
FROM employee
ORDER BY salary DESC) )
SELECT MAX(Salary) FROM Employee
WHERE Salary NOT IN (SELECT MAX(Salary) FROM Employee)
If you want to display the name of the employee who is getting the second highest salary then use this:
SELECT employee_name
FROM employee
WHERE salary = (SELECT max(salary)
FROM employee
WHERE salary < (SELECT max(salary)
FROM employee);
Try This one
select * from
(
select name,salary,ROW_NUMBER() over( order by Salary desc) as
rownum from employee
) as t where t.rownum=2
http://askme.indianyouth.info/details/write-a-sql-query-to-find-the-10th-highest-employee-salary-from-an-employee-table-explain-your-answer-111
Try this to get the respective nth highest salary.
SELECT
*
FROM
emp e1
WHERE
2 = (
SELECT
COUNT(salary)
FROM
emp e2
WHERE
e2.salary >= e1.salary
)
Select * from employee where salary = (Select max(salary) from employee where salary not in(Select max(salary)from employee))
Explanation :
Query 1 : Select max(salary) from employee where salary not in(Select max(salary) from employee) - This query will retrieve second highest salary
Query 2 : Select * from employee where salary=(Query 1) - This query will retrieve all the records having second highest salary(Second highest salary may have multiple records)
I think this is probably the simplest out of the lot.
SELECT Name FROM Employees group BY Salary DESCENDING limit 2;
Try this: This will give dynamic results irrespective of no of rows
SELECT * FROM emp WHERE salary = (SELECT max(e1.salary)
FROM emp e1 WHERE e1.salary < (SELECT Max(e2.salary) FROM emp e2))**
Here's a simple approach:
select name
from employee
where salary=(select max(salary)
from(select salary from employee
minus
select max(salary) from employee));
I want to post here possibly easiest solution. It worked in mysql.
Please check at your end too:
SELECT name
FROM `emp`
WHERE salary = (
SELECT salary
FROM emp e
ORDER BY salary DESC
LIMIT 1
OFFSET 1
declare
cntr number :=0;
cursor c1 is
select salary from employees order by salary desc;
z c1%rowtype;
begin
open c1;
fetch c1 into z;
while (c1%found) and (cntr <= 1) loop
cntr := cntr + 1;
fetch c1 into z;
dbms_output.put_line(z.salary);
end loop;
end;
Using this SQL, Second highest salary will get with Employee Name
Select top 1 start at 2 salary from employee group by salary order by salary desc;

SQL query: how can I get "id" of department in which employees receive the maximum salary?

How can I get id of department in which employees receive the maximum salary:
Employee table: Empl (ID, FirstName, LastName, Salary, DeptId)
Departments table: Dept (ID, City)
rus (Вывести “id” подразделения, в котором сотрудники получают максимальную заработную плату.)
EDIT: Changed SUM(Salary) to AVG(Salary) based on comments on the question.
SELECT TOP 1 DeptId
FROM Employees
GROUP BY DeptId
ORDER BY AVG(Salary) DESC
SELECT TOP 1 B.*
FROM (SELECT DeptId, AVG(Salary) AvgSalary
FROM Empl
GROUP BY DeptId) A
INNER JOIN Dept B
ON A.DeptId = B.Id
ORDER BY AvgSalary DESC
To get the one single Department's ID where the highest single salary is paid:
SELECT TOP 1 DeptID
FROM dbo.Empl
ORDER BY Salary DESC
Or are you looking for something else?
I would assume you mean max average salary of a department and not the single highest salary across all departments.
However it seems all you would have to do is use the following SQL functions
MAX function
AVG function
group by department ID and viola.
Thought I agree with the comments above, I will assume you are doing this for research ;-)
select id
from dept
where id = ( select deptid
from ( select max(avg_salary), deptid
from ( select deptid, avg(salary) as avg_salary
from empl
group by deptid )
group by deptid )
)
:-)
SELECT DepartmentId
FROM Employee
WHERE Salary = (SELECT MAX(Salary) FROM Employee)

what is the query to return Name and Salary of employee Having Max Salary

what is the query to return Name and Salary of employee Having Max Salary
SELECT Name, Salary FROM Minions
WHERE Salary = (SELECT Max(Salary) FROM Minions)
Note that this will return more than one row if there is more than one employee who have the same max salary
select name, salary from (select * from salary_table order by salary desc limit 1)
SELECT FirstName, max(salary)
FROM Employees
WHERE salary = (
SELECT max(salary)
FROM employees
)
GROUP BY FirstName
working in SQL SERVER 2012
A couple of proprietary solutions
SELECT TOP 1 [WITH ties] Name, Salary
FROM employee
ORDER BY Salary DESC
SELECT Name, Salary
FROM employee
ORDER BY Salary DESC
LIMIT 1
And a standard one
WITH E AS
(
SELECT Name, Salary,
ROW_NUMBER() OVER (ORDER BY Salary DESC) RN /*Or RANK() for ties*/
FROM employee
)
SELECT Name, Salary FROM E WHERE RN=1
In case there are multiple rows with the same MAX number then you can just limit the number to desired number like this
SELECT Name, Salary FROM Minions
WHERE Salary = (SELECT Max(Salary) FROM Minions) LIMIT 1
Select e.name, e.salary from employee e where
not exists (select salary from employee e1 where e.salary < e1.salary)
This will of course return more than one record if there are multiple people with the max salary.
If you are using an oracle database and only want a single "employee" then:
SELECT MAX( name ) KEEP ( DENSE_RANK LAST ORDER BY salary ASC ) AS name,
MAX( salary ) KEEP ( DENSE_RANK LAST ORDER BY salary ASC ) AS salary
FROM Minions;
SQLFIDDLE
(kudos to Neil N for his table name)
SQL Server has a similar FIRST_VALUE (or LAST_VALUE) analytic function.
PostgreSQL also supports window functions including LAST_VALUE.
These type of queries (grouped operaions) can execute with sub query.
Example
select *from emp where sal=(max(sal)from emp)
Assuming only one employee has maximum salary
SQL Server:
select top 1 name, salary
from employee
order by salary desc
Oracle:
select name, salary
from employee
order by salary desc
limit 1
Above queries scans the table only once unlike other queries using subqueries.