Contents

SQL Practices 01

175. Combine Two Table

Write a SQL query for a report that provides FirstName, LastName, City, State for each person in the Person table, regardless if there is an address for each of those people

  • PersonId and AddressId are primary keys
1
2
3
4
5
6
Create table Person (PersonId int, FirstName varchar(255), LastName varchar(255))
Create table Address (AddressId int, PersonId int, City varchar(255), State varchar(255))
Truncate table Person
insert into Person (PersonId, LastName, FirstName) values ('1', 'Wang', 'Allen')
Truncate table Address
insert into Address (AddressId, PersonId, City, State) values ('1', '2', 'New York City', 'New York')

Solution: Outter Join

Since the PersonId in table Address is the foreign key of table Person, we can join this two table to get the address information of a person.

  • Considering there might not be an address information for every person, we should use outer join instead of the ~default inner join~.
  • Using where clause to filter the records will FAIL if there is no address information for a person
    • because it will not display the name information.
1
2
3
4
select FirstName, LastName, City, State
from Person left join Address
on Person.PersonId = Address.PersonId
;

176. Second Highest Salary

Write a SQL query to get the second highest salary from the Employee table.

1
2
3
4
5
Create table If Not Exists Employee (Id int, Salary int)
Truncate table Employee
insert into Employee (Id, Salary) values ('1', '100')
insert into Employee (Id, Salary) values ('2', '200')
insert into Employee (Id, Salary) values ('3', '300')

Solution 1 - Using sub-query and LIMIT clause

Sort the distinct salary in descend order and then utilize the LIMIT clause to get the second highest salary.

1
2
3
4
5
6
SELECT
    (SELECT DISTINCT Salary
        FROM Employee
        ORDER BY Salary DESC
        LIMIT 1 OFFSET 1) AS SecondHighestSalary

Solution 2 - Using IFNULL and LIMIT clause

1
2
3
4
5
6
7
SELECT
    IFNULL(
      (SELECT DISTINCT Salary
       FROM Employee
       ORDER BY Salary DESC
       LIMIT 1 OFFSET 1),
    NULL) AS SecondHighestSalary

177. Nth Highest Salary

Write a SQL query to get the nth highest salary from the Employee table.

Solution

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
DECLARE M INT;
SET M=N-1;
  RETURN (
      SELECT DISTINCT Salary
      FROM Employee
      ORDER BY Salary DESC
      LIMIT 1 OFFSET M
  );
END

178. Rank Scores

Write a SQL query to rank scores. If there is a tie between two scores, both should have the same ranking.

Solution 1 - Window Function dense_rank()

The difference between dense_rank() and rank() is that after a tie, the next ranking number should be the next consecutive integer value when using dense_rank()

1
2
3
SELECT Score,
       dense_rank() OVER(ORDER BY Score DESC) AS `Rank`
FROM Scores;

Solution 2 - General

A Score’s Rank is the count of Distinct Score(includes itself) larger or equal to it

1
2
3
4
5
SELECT S1.Score, COUNT(S2.Score) AS `Rank`
FROM Scores S1, (SELECT DISTINCT Score FROM Scores) S2
WHERE S2.Score >= S1.Score
GROUP BY S1.Id
ORDER BY S1.Score DESC;

180. Consecutive Numbers

Write an SQL query to find all numbers that appear at least three times consecutively.

Solution

1
2
3
4
5
6
7
# Logs (Id int, Num int)
SELECT DISTINCT l1.Num AS ConsecutiveNums
FROM Logs l1, Logs l2, Logs l3
WHERE
    l1.Id = l2.Id - 1 AND l2.Id = l3.Id - 1
    AND l1.Num = l2.Num AND l2.Num = l3.Num
;

181. Employees Earning More Than Their Managers

Given the Employee table, write a SQL query that finds out employees who earn more than their managers.

Solution - Use JOIN ON or WHERE

  • JOIN and ON could be , and WHERE
1
2
3
4
5
6
# Employee (Id int, Name varchar(255), Salary int, ManagerId int)
SELECT e1.NAME AS Employee
FROM Employee e1 JOIN Employee e2
ON e1.ManagerId = e2.Id
AND e1.Salary > e2.Salary
;

182. Duplicate Emails

Write a SQL query to find all duplicate emails in a table named Person.

Solution - GROUP BY and HAVING

1
2
3
4
5
# Person (Id int, Email varchar(255))
SELECT Email
FROM Person
GROUP BY Email
HAVING count(Email) > 1;

183. Customers Who Never Order

Suppose that a website contains two tables, the Customers table and the Orders table. Write a SQL query to find all customers who never order anything.

Solution 1 - NOT IN

1
2
3
4
5
# Customers (Id int, Name varchar(255))
# Orders (Id int, CustomerId int)
SELECT Customers.Name AS Customers
FROM Customers
WHERE Customers.Id NOT IN (SELECT Customerid FROM Orders);

Solution 2 - LEFT JOIN

1
2
3
4
5
6
7
# Customers (Id int, Name varchar(255))
# Orders (Id int, CustomerId int)
SELECT Customers.Name as Customers
FROM Customers
LEFT JOIN Orders
ON Customers.Id=Orders.CustomerId
WHERE Orders.CustomerId IS NULL;

184. Department Highest Salary

Write a SQL query to find employees who have the highest salary in each of the departments.

Solution - Inner Join

Employee cannot find the empty Department when using LEFT JOIN

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Employee (Id int, Name varchar(255), Salary int, DepartmentId int)
# Department (Id int, Name varchar(255))
SELECT
    Department.name AS 'Department',
    Employee.name AS 'Employee',
    Salary
FROM Employee JOIN Department
ON Employee.DepartmentId = Department.Id
WHERE (Employee.DepartmentId , Salary) IN
    (   SELECT DepartmentId, MAX(Salary)
        FROM Employee
        GROUP BY DepartmentId
    )
;

185. Department Top Three Salaries

Write an SQL query to find the employees who has a salary in the top three unique salaries in each of the departments.

Solution 1 - Using JOIN and sub-query

A top 3 salary in this company means there is no more than 3 salary bigger than itself in the company.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# Employee (Id int, Name varchar(255), Salary int, DepartmentId int)
# Department (Id int, Name varchar(255))
SELECT Department.Name AS Department, e1.Name AS Employee, e1.Salary
FROM Employee e1 JOIN Department ON e1.DepartmentId = Department.Id
WHERE
    3 > (SELECT COUNT(DISTINCT e2.Salary)
        FROM Employee e2
        WHERE e2.Salary > e1.Salary
        AND e1.DepartmentId = e2.DepartmentId
        )
;
# e.g.e1 = e2 = [4,5,6,7,8]
# - e1.Salary = 4e2.Salary => [5,6,7,8]count(DISTINCT e2.Salary) = 4
# - e1.Salary = 5e2.Salary => [6,7,8]count(DISTINCT e2.Salary) = 3
# - e1.Salary = 6e2.Salary => [7,8]count(DISTINCT e2.Salary) = 2 `< 3`
# - e1.Salary = 7e2.Salary => [8]count(DISTINCT e2.Salary) = 1 `< 3`
# - e1.Salary = 8e2.Salary =>  []count(DISTINCT e2.Salary) = 0 `< 3`
# - 3 > count(DISTINCT e2.Salary) Top3 = [6,7,8]

Solution 2 -