Leetcode 176. Second highest salary - mysql

In a given question,
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 submited the query below
(window function to rank the salary then identify ifnull or not):
WITH salary_ranked
AS (
SELECT
salary,
DENSE_RANK() OVER (ORDER BY salary DESC) AS rank_num
FROM
Employee
)
SELECT
IFNULL(
(SELECT salary_ranked.salary
FROM salary_ranked
WHERE rank_num =2), 'null') AS SecondHighestSalary;
But it showed the wrong answer as below.
THE LATEST UPDATE
Revised the code below:
WITH salary_ranked
AS (
SELECT
salary,
DENSE_RANK() OVER (ORDER BY salary DESC) AS rank_num
FROM
Employee
WHERE
salary > 0
)
SELECT
IFNULL(
(SELECT salary_ranked.salary
FROM salary_ranked
WHERE rank_num =2), null) AS SecondHighestSalary;
It passed 7 test cases of 8. But it still leave the last situation to be solved.

SELECT id, salary FROM employees ORDER BY salary DESC LIMIT 1, 1
The first number after "LIMIT" is the offset when using the comma. The offset is zero-indexed. So, this query selects one row, starting at the second highest.
See the section on "offset" in the MySQL docs on SELECT

Related

how to find the nth highest number when values of the numbers are the same

SQL Question:
Write a SQL query to get the nth highest salary from the Employee table (SQL Server)
| Id | Salary |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
For this example, the nth highest salary where n = 2 is 200. If there is no nth highest salary, then the query should return null.
| getNthHighestSalary(2) |
+------------------------+
| 200 |
My code is the following:
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
RETURN (
select distinct a.salary from Employee a, Employee b where
a.id =b.id-n+1 order by a.id desc
limit 1
);
END
My question is: The code works for most of the cases except for the situation when there are multiple same values before the nth place. For example, whe n is 2 and the table is the following. (The expected result should be NULL and my code returns 100. ) So, how can I change my code so that it can work for all situations? Thank you!
+----+--------+
| id | salary |
+----+--------+
| 1 | 100 |
| 2 | 100 |
| 3 | 100 |
+----+--------+
Try this
Select distinct salary
From (
Select salary, dense_rank() over
(order by salary desc) r
from employee
) where r=n
1st 2nd and 3rd highest salary query
SELECT MAX(salary) AS ThirdHighestSalary
FROM emp
WHERE (salary <
(SELECT MAX(salary) AS SecondHighestSalary
FROM emp
WHERE (salary <
(SELECT MAX(salary) AS HighestSalary
FROM emp))))

Rank in subquery

I'm looking to report the best seller by total sales price using the table below:
Sales table:
seller_id | quantity | price
| 1 | 2 | 2000 |
| 1 | 1 | 800 |
| 2 | 1 | 800 |
| 3 2 | 2800 |
The result need to be 1 & 3 (a table with 1 column "seller_id")since both sellers with id 1 and 3 sold products with the most total price of 2800
I tried to write a query using rank.. in a subquery, I will have something like:
SELECT
sum(price), rank() over (order by price desc )
FROM
sales
group by seller_id
Then, I need to select the sum(price) with rank=1, but I don't know how to write that..
Then, outside of the subquery, I want to select just the seller_id.
How do we do these?
Use RANKING function for retrieving seller_id based on highest price. RANK() function serialize the position with a GAP. If two values in same position then third value position after this to value will 3 not 2.
-- MySQL (v5.8)
SELECT t.seller_id, t.total_price
FROM (SELECT seller_id, SUM(price) total_price
, RANK() OVER (ORDER BY SUM(price) DESC) rank_price
FROM sales
GROUP BY seller_id) t
WHERE t.rank_price = 1
DENSE_RANK() function serialize the position without a GAP. If top 5 price needed in future then it'll better.
-- MySQL (v5.8)
SELECT t.seller_id, t.total_price
FROM (SELECT seller_id, SUM(price) total_price
, DENSE_RANK() OVER (ORDER BY SUM(price) DESC) rank_price
FROM sales
GROUP BY seller_id) t
WHERE t.rank_price = 1
Please check from url https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=90c756fa6d3ab25914721cfe40df5e9a

Getting second highest Salary value in MySQL

In a given question,
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 wrote a code for this question, however, the expected output is different.
My Code:
SELECT
CASE
WHEN COUNT(*) = 1 THEN NULL
ELSE (SELECT Salary FROM Employee HAVING Salary < MAX(Salary) ORDER BY Salary DESC LIMIT 1)
END AS SecondHighestSalary
FROM Employee;
I think there's something wrong with my code but I cannot find what is the actual problem here. My code returns 100 not 200. What have I gotten wrong?
+---------------------+
| SecondHighestSalary |
+---------------------+
| 100 |
+---------------------+
You can utilize LIMIT {[offset,] row_count}. Refer https://dev.mysql.com/doc/refman/8.0/en/select.html
Order by Salary in descending order, and get the second row by defining OFFSET as 1. We will use DISTINCT on Salary as there is a possibility to have multiple rows for the highest salary.
SELECT DISTINCT
Salary
FROM Employee
ORDER BY Salary DESC
LIMIT 1,1
You can try below
SELECT MAX(salary) From Employee WHERE salary < ( SELECT Max(salary) FROM Employee);
Try that out:
SELECT salary FROM Employee ORDER BY salary DESC LIMIT 1,1
or to a deeper approach you can use something like:
SELECT salary FROM Employee GROUP BY salary ORDER BY salary DESC LIMIT 1,1
All that queries have high performance, since they does not have any subqueries.
If you want to display a empty_row(null) in case there is no highest salary then the following does it, if there is a value then it gets shown
select (select salary
from Employee ORDER BY salary DESC LIMIT 1,1
) as x
Here is the solution.
SELECT MAX(salary) From Employee WHERE salary < ( SELECT Max(salary) FROM Employee);

Using only agregate function on determined row

I have to use only aggregate function (so without checking exact values in columns, for determined row), when I select the determined IT worker's salary.
It isn't as simple as SELECT SUM(salary) FROM table WHERE occupation='IT worker' LIMIT <here stays which place the person has on the list>, 1, is it? I think that by using SUM command, we don't check exact values.
If this question isn't understandable, I can translate the whole exercise.
EDIT: the exercise
Using only agregate functions (without checking exact values in columns, for determined row) create a query, which lets us know about determined IT worker's salary. table contains:
id int
occupation varchar(50)
salary int
I am not going to write the queries, this is meant to get you started:
The table seems to have 3 fields: id, occupation, and salary.
Each row seems to correspond to a specific worker
Then you can use agregate functions to calculate stuff regarding different occupations (for example).
The structure for a query that uses agregate functions is like this:
Select <fields and agregate functions>
from table
where <filter records to consider for the query before aggregation>
group by <field having the same value, hence that can be grouped by>
having <optional condition evaluated after doing the aggregation>
Examples of agregate functions are Sum, Count, Avg.
The question is not clear but with the informatin you have you can calculate:
Number of workers with same occupaton.
Average salary.
Total salary income by occupation.
If we ignore department for now you could do something like this
MariaDB [sandbox]> select emp_no, salary from employees ;
+--------+--------+
| emp_no | salary |
+--------+--------+
| 1 | 20000 |
| 2 | 39500 |
| 3 | 50000 |
| 4 | 19500 |
| 5 | 10000 |
| 6 | 19500 |
| 7 | 40000 |
| 9 | NULL |
+--------+--------+
8 rows in set (0.00 sec)
MariaDB [sandbox]> select emp_no,salary,
-> concat(rank,' of ' ,obs) as Rank,
-> Position,
-> reltoavg realtivetoavg
-> from
-> (
-> select emp_no,salary ,
-> #rn:=#rn+1 as Rank,
-> (select count(*) from employees) as obs,
-> concat('There are ',
-> (Select count(*) from employees e1 where e1.SALARY > e.salary) , ' employees who earn more and ',
-> (Select count(*) from employees e1 where e1.SALARY < e.salary and salary is not null) , ' who earn less') Position,
-> (select avg(salary) from employees) avgsalary,
-> if (salary > (select avg(salary) from employees), 'Salary is above average', 'salary is below average') reltoavg
-> from employees e,(Select #rn:=0) r
-> where salary is not null
-> order by salary
-> ) s
-> where s.emp_no = 1
-> ;
+--------+--------+--------+---------------------------------------------------------+-------------------------+
| emp_no | salary | Rank | Position | realtivetoavg |
+--------+--------+--------+---------------------------------------------------------+-------------------------+
| 1 | 20000 | 4 of 8 | There are 3 employees who earn more and 3 who earn less | salary is below average |
+--------+--------+--------+---------------------------------------------------------+-------------------------+
1 row in set (0.00 sec)

MAX function in MySQL does not return proper key value

I have a table called tbl_user_sal:
| id | user_id | salary | date |
| 1 | 1 | 1000 | 2014-12-01 |
| 2 | 1 | 2000 | 2014-12-02 |
Now I want to get the id of the maximum date. I used the following query:
SELECT MAX(date) AS from_date, id, user_id, salary
FROM tbl_user_sal
WHERE user_id = 1
But it gave me this output:
| id | user_id | salary | from_date |
| 1 | 1 | 2000 | 2014-12-02 |
Which is correct as far as the max date being 2014-12-02, but the corresponding id is not correct. This happens for other records as well. I used order by to check but that was not successful either. Can anyone shed some light on this?
Note: Its not necessary that max date will have max id, according to my needs. Records can have max date but id may be older.
If you only want to retrieve that information for a single user, which you seem to, because of your WHERE clause, just use ORDER BY and LIMIT:
SELECT *
FROM tbl_user_sal
WHERE user_id = 1
ORDER BY date DESC
LIMIT 1
If you want to do that for every user, however, you will have to get a little bit fancier. Something like that should do it:
SELECT t2.id, user_id, date
--find max date for each user_id
FROM (SELECT user_id, MAX(date) AS date
FROM tbl_user_sal
GROUP BY user_id) AS t1
--join ids for each max date/user_id combo
JOIN tbl_user_sal AS t2
USING (user_id, date)
--limit to 1 id for every user_id
GROUP BY
user_id
You are missing group by clause Try this:
select max(awrd_date) as from_date,awrd_id
from tbl_user_sal
where awrd_user_id = 106
group by awrd_id
What I believe you should do here is have a subquery that pulls the max date, and your outer query looks for the row with that date.
It looks like this:
SELECT *
FROM myTable
WHERE date = (SELECT MAX(date) FROM myTable);
Additional things may need to be added if you want to search for a specific user_id, or get the largest date for each user_id, but this gives your expected results for this example here.
Here is the SQL Fiddle.