Find second highest highest query doesn't work - mysql

I could not figure out why my query does not work. The errors shows aggregate function have to use group by. I add "group by MAX(Salary)" which can not do the trick. Please help, thanks!
Table:
Query
SELECT Name, MAX(Salary)
FROM PRACTICE.SALARY
WHERE Salary
NOT IN (SELECT MAX(Salary) FROM PRACTICE.SALARY);

When you use aggregate function you need to add non-aggregate columns in group by
SELECT Name, MAX(Salary)
FROM PRACTICE.SALARY
WHERE Salary
NOT IN (SELECT MAX(Salary) FROM PRACTICE.SALARY)
GROUP BY Name
but If you only want to get second heigh SALARY, your query will get the wrong result because you group by for each NAME and get MAX(Salary) will get every Salary of Max from each NAME instead of the whole table.
I think you can use this query to get your expect result.
Schema (MySQL v5.7)
CREATE TABLE T(
Name VARCHAR(50),
Salary int
);
INSERT INTO T VALUES ('Lucy',2008);
INSERT INTO T VALUES ('PETER',3000);
INSERT INTO T VALUES ('K',1900);
INSERT INTO T VALUES ('TOM',2015);
INSERT INTO T VALUES ('MARK',3001);
Query #1
SELECT Name, Salary
FROM PRACTICE.SALARY
WHERE Salary <> (SELECT MAX(Salary) FROM PRACTICE.SALARY)
ORDER BY Salary DESC
LIMIT 1;
| Name | Salary |
| ----- | ------ |
| PETER | 3000 |
View on DB Fiddle

Related

Using dense_rank to find the 2nd highest salary in MYSQL

I am trying to do this Leetcode question where we try to find the 2nd highest salary from the EMPLOYEE TABLE.
INPUT :
+-------------+------+
| Column Name | Type |
+-------------+------+
| id | int |
| salary | int |
+-------------+------+
id is the primary key column for this table.
Each row of this table contains information about the salary of an employee.
My answer is the following. But leetcode is not accepting this answer. What if I don't want to use the offset clause and use the dense function? Can it be done? Kindly help.
with temp1 as
(select id, salary, dense_rank() over (order by salary desc) as salary_order
from employee)
select coalesce(salary, null) as SecondHighestSalary
from temp1
where salary_order=2;
Question Link: https://leetcode.com/problems/second-highest-salary/
DENSE_RANK() is fine for this problem, but if you filter the cte and there is no 2nd highest salary, the query will not return null.
Also, coalesce(salary, null) would just return null if salary is already null, so it does not help.
With conditional aggregation you can get the 2nd highest salary and null if it does not exist:
WITH cte AS (SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS salary_order FROM employee)
SELECT MAX(CASE WHEN salary_order = 2 THEN salary END) AS SecondHighestSalary
FROM cte;
See the demo.

SQL Case When not labeling null

I'm trying to do this Leet Code Problem:
Write a SQL query to get the second highest salary from the Employee table.
+----+--------+
| Id | Salary |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+--------+
For example, given the above Employee table, the query should return 200 as the second highest salary. If there is no second highest salary, then the query should return null.
+---------------------+
| SecondHighestSalary |
+---------------------+
| 200 |
+---------------------+
I'm trying to give this solution:
SELECT
CASE WHEN Salary = ''
THEN NULL
ELSE Salary END SecondHighestSalary
FROM
Employee
ORDER BY
SecondHighestSalary
LIMIT 1,1;
When there is a second salary, it works fine and returns the output. However, when there is no second salary and there's only one salary only an empty string is returned. I'm trying to return NULL, however, it doesn't return NULL like what I wrote in my query. How can I fix this?
Your CASE expression is testing the salary in each row of the table, not the one selected by the LIMIT clause. Ordering is done after generating the values in the SELECT list, since you can order by those calculated values.
Since none of the salaries are empty strings, the condition in your CASE will never be true, so it always returns the Salary value. As a result, your query is equivalent to
SELECT Salary AS SecondHighestSalary
FROM Employee
ORDER BY SecondHighestSalary
LIMIT 1, 1
Other things:
You need to use DESC to get the highest salary at the beginning. So even if your method worked, it would find the second lowest salary.
Your method doesn't handle the case where multiple employees are tied for the highest salary. LIMIT 1, 1 will return the second row, which will be one of the tied employees.
You can solve the second problem using a subquery that removes duplicates:
SELECT DISTINCT Salary
FROM Employee
So a final query could be:
SELECT IF(COUNT(*) > 0, MAX(Salary), NULL) AS SecondHighestSalary
FROM (
SELECT DISTINCT Salary
FROM Employee
ORDER BY Salary DESC
LIMIT 1, 1
) AS x
You can use this solution, where if there have no second highest salary will return NULL. Otherwise will return second highest salary
SELECT
IFNULL(MIN(Salary) , 'NULL') as SecondHighestSalary
FROM
Employee
WHERE salary > (SELECT MIN(salary)
FROM Employee)
Or if you want DB default null then just remove IFNULL condition
SELECT
MIN(Salary) as SecondHighestSalary
FROM
Employee
WHERE salary > (SELECT MIN(salary)
FROM Employee)
E.g.
select max(salary) salary
from employee
where salary not in
(select max(salary) from employee)

SQL: Do all attributes in a GROUP BY clause need to be listed in the SELECT clause?

Say I have a table called Employee with attributes Name, Salary, Department.
I know that this will work:
SELECT Department, AVG(Salary)
FROM EMPLOYEE
GROUP BY Department;
Would it be incorrect to discard 'Department' from the SELECT clause like so:
SELECT AVG(Salary)
FROM EMPLOYEE
GROUP BY Department;
Or would it still work?
Both queries will work and provide the output. However, second query will only result in one column (i.e. average salary) and hence, you won't be able to trace it back to department id from second query alone, e.g.:
Query 1 output:
dept | salary
1 | 5000
2 | 6000
Query 2 output:
salary
5000
6000
no, not necessarily. You can use the 2nd query too.But you can't see for which depart the salary got sorted by 'group-by' key-word.

Find Total salary using distinct and sum?

How to get the sum of distinct IDs and their respective salaries?
ID Salary
1 1000
2 2000
1 1000
2 2000
In above I want to get the out like this
Total salary
3000
I tried and made the output like this
ID Salary
1 1000
2 2000
select distinct(id), sum (salary) from employee group by id
Main issue is that I am not able to total after applying distinct to the ID.
Want to remove the duplicate entries of id and sum of there distinct ID?
Check this Query is,
Query
SELECT SUM (
DISTINCT salary
) FROM employee
Result
SUM(DISTINCT SALARY)
--------------------
3000
Check Demo SQLFiddle
You can do also by this way,
SELECT SUM(salary)
FROM (SELECT DISTINCT id, salary
FROM employee
GROUP BY id,salary
) AS emp
Check this Demo SQLfiddle
Try this 100% work
SELECT SUM(salary) as "Total salary"
FROM(SELECT DISTINCT id, salary FROM
employee GROUP BY id,salary ) as e
Try Like This
select sum(salary) from( select distinct id, salary from
employee) as t
Simplest way would be, remove duplicate records and write simple query. Second way is this query, in which I have taken MAX(Highest) salary for each employee in sub query, and then applied SUM() from calculating total salary.
SELECT SUM (sal) from
(
SELECT MAX (salary) as sal
FROM employee GROUP BY id
) as tbl
Try this:
It will work definitely
It will sum of salary with same id only.
Select SUM(salary) as total from employee group by id;

SQL max() function returns wrong value for row with maximum value

THIS IS MY TABLE STRUCTURE:
Anees 1000.00
Rick 1200.00
John 1100.00
Stephen 1300.00
Maria 1400.00
I am trying to find the MAX(salary) and the persons name .
this is the query I use
Select MAX(salary),emp_name
FROM emp1
I get 1400.00 and Anees.
While the 1400 is correct the Anees is wrong,it should be maria. What changes do I need to make
MySQL allows you to have columns in the select statement that are not in aggregate functions and are not in the group by clause. Arbitrary values are returned.
The easiest way to do what you want is:
select t.*
from t
order by salary desc
limit 1;
Gordon gave an explanation why and the simplest way to get want you want. But if you for some reason want to use MAX() you can do it like this
SELECT emp_name, salary
FROM emp1
WHERE salary =
(
SELECT MAX(salary) salary
FROM emp1
)
Output:
| EMP_NAME | SALARY |
---------------------
| Maria | 1400 |
Here is SQLFiddle demo
It's giving the wrong output because of the datatype you mentioned. If you mentioned the salary datatype number or integer, it will give you the correct answer.
It will give you the correct answer no problem make sure your datatype is integer or number.
select max(salary) from emp;