Leetcode 176 : Second Highest Salary
Employee 테이블에서 2번째로 높은 Salary를 찾는 문제
만약 2번째로 높은 값이 없다면 null을 반환해야 한다
이 문제를 처음 접했을 때 가장 먼저 구상했던 풀이 방법이다.
row_number() over (order by salary desc)를 통해서 rn을 구하고,
rn=2인 값을 뽑으면 간단히 문제 해결!
이라고 생각했지만,
WHERE절에 rn=2를 넣으면, FROM에서 애초에 rn=2인 값이 존재하지 않는 데이터의 경우에는 null조차 반환하지 못 한다
이를 해결하기 위해 CASE END 조건문에 count(*)를 넣을 수 있다
FROM절에서 (WHERE 처리까지 하고) 반환된 값이 0개라면 -> rn=2인 값이 없는 상태
1개라면 -> rn=2인 값이 있는 상태
로 볼 수 있기 때문.
SELECT
CASE
when count(*)=0 then null
else salary
end as "SecondHighestSalary"
FROM (
SELECT
salary
, row_number() over (order by salary desc) as "rn"
FROM
(SELECT
distinct salary
FROM
Employee
) a
) aa
WHERE
rn = 2
;
위에서 고민했던 부분이 'null이 출력되지 않는 경우'였다.
이를 해결하기 위해 max() 함수를 사용할 수 있다.
MAX() 함수는 집계 함수이다. 집계 함수는 입력으로 받은 행들이 하나도 없을 때, 즉 빈 집합에 대해 적용되면 결과로 NULL을 반환하는 특징이 있다.
이를 통해 별도로 조건을 걸지 않아도 값이 없다면 null이 출력되게 할 수 있다.
SELECT
MAX(salary) AS "SecondHighestSalary"
FROM (
SELECT
salary
, ROW_NUMBER() OVER (ORDER BY salary DESC) AS rn
FROM (
SELECT
DISTINCT salary
FROM
Employee) a
) b
WHERE rn = 2
;
참고: [MYSQL] 📚 LIMIT / OFFSET 쿼리
LIMIT는 단순히 ‘몇 개’를 가져온다에 그치지 않고 ‘어디서부터’를 지정해줄 수도 있다
LIMIT 2 : 처음부터 2개 출력하기 (1~2)
LIMIT 1, 2 : 1번째 행 후부터 2개 출력하기 (2~3)
LIMIT 2 OFFSET 1 : 1번째 행 후부터 2개 출력하기 (2~3)
이를 통해 "2번째 행부터 1개"를 지정해주면 문제에서 요구하는 바를 정확하게 뽑아낼 수 있다
다만, 그냥 LIMIT만 사용하면 null 처리가 불가능하기 때문에,
값이 존재하지 않을 경우 null을 출력하기 위해 SELECT 문으로 전체 결과를 감싸주어야 한다
SELECT (
SELECT
distinct salary
FROM
Employee
ORDER BY
salary desc
LIMIT
1, 1
) as "SecondHighestSalary"
;