๐ ๋ณธ ํฌ์คํ ์์ ์ฌ์ฉ๋๋ ํ ์ด๋ธ์ ์๋ฃ์ ์ถ์ฒ๋ Leetcode์์ ๋ฐํ๋๋ค. ๋ ๋ค์ํ SQL ๋ฌธ์ ๋ฅผ ํ์ด๋ณด์๋ ค๋ฉด Leetcode ์ฌ์ดํธ๋ฅผ ๋ฐฉ๋ฌธํด ๋ณด์ธ์!
์ด๋ฒ ํฌ์คํ ์์๋ MySQL 8.0 ๋ฒ์ ๋ถํฐ ํธํ์ด ๊ฐ๋ฅํ Window Function์ ์ด์ฉํด ๋ฌธ์ ๋ฅผ ํ์ด๋ณด์. ๋ง์ฝ MySQL 8.0 ์ดํ ๋ฒ์ ์ด๋ผ๋ฉด MSSQL์ ํ์ฉํด Window Function์ ๊ตฌํํ ์ ์๋ค. Window Function์ ๋ํด์๋ ๊ณต์ ๋ฌธ์๋ฅผ ์ฐธ์กฐํด๋ณด์. ์๋นํ ์ ์ฉํ ๊ธฐ๋ฅ๋ค์ด ๋ง๋ค.
์ด๋ฒ์๋ ์ด 3๊ฐ์ ๋ฌธ์ ๋ฅผ ํ์ด๋ณผํ ๋ฐ ๋์ด๋๊ฐ ์ด๋ ์ ๋ ์๋ ๋ฌธ์ ๋ค์ด๋ค. ๋ฐ๋ผ์ ์์ธํ ๋ฌธ์ ๋ ์ฌ๊ธฐ๋ฅผ ํด๋ฆญํด 180๋ฒ, 184๋ฒ, 185๋ฒ ๋ฌธ์ ๋ฅผ ์์ธํ ์ฝ์ด๋ณด์.
# 180๋ฒ
๋จผ์ ๋ฌธ์ ์ ๋ฌธ์ ์์ ์๊ตฌํ๋ ์ถ๋ ฅํํ๋ฅผ ์ดํด๋ณด์.
Write an SQL query to find all numbers that appear at least three times consecutively. Return the result table in any order.
(์ ์ด๋ ์ฐ์์ผ๋ก 3๋ฒ ๋ํ๋๋ ๋ชจ๋ ์ซ์๋ค์ ์ฟผ๋ฆฌํด๋ผ. ๊ฒฐ๊ณผ๊ฐ์ ๋ฐ์ดํฐ๋ค ์ ๋ ฌ ์์๋ ๋ฐ๋ก ์ง์ ํด์ฃผ์ง ์์๋ ๋๋ค.)
ํด๋น ๋ฌธ์ ๋ฅผ ํ๊ธฐ ์ํด์๋ Window Function ์ค ๊ฐ์ ๋ฐ์ด๋ด๋ LAG(๊ฐ, ์ผ๋ง๋ lag์ํฌ์ง) ์ ๊ฐ์ ๋ก๊ฒจ์ค๋ LEAD(๊ฐ, ์ผ๋ง๋ lead์ํฌ์ง) ๋ฅผ ์ด์ฉํ 2๊ฐ์ง ํ์ด๊ฐ ์๋ค. ์ฐ์ LAG() ๋ฅผ ์ฌ์ฉํ ํ์ด๋ ๋ค์๊ณผ ๊ฐ๋ค.
-- LAG๋ฅผ ์ด์ฉํ ํ์ด
SELECT DISTINCT sub.Num AS ConsecutiveNums
FROM (SELECT Num,
LAG(Num, 1) OVER (ORDER BY Id) AS next,
LAG(Num, 2) OVER (ORDER BY Id) AS nextAfter
FROM Logs) sub
WHERE sub.Num = sub.next AND sub.next = sub.nextAfter
์ ์ฟผ๋ฆฌ ์ค ์๋ธ์ฟผ๋ฆฌ์ ์๋ SELECT ๋ฌธ๋ง ์ฟผ๋ฆฌํ์ ๋ ํ ์ด๋ธ ์ถ๋ ฅ ํํ๋ ๋ค์๊ณผ ๊ฐ๋ค.
Id | Num | next | nextAfter |
1 | 1 | null | null |
2 | 1 | 1 | null |
3 | 1 | 1 | 1 |
4 | 2 | 1 | 1 |
5 | 1 | 2 | 1 |
6 | 2 | 1 | 2 |
7 | 2 | 2 | 1 |
๊ทธ๋์ ์ ํ ์ด๋ธ์ FROM ์ดํ์ ์๋ธ์ฟผ๋ฆฌ๋ก ๋ฃ์ด์ฃผ์ด์ ์ ํ ์ด๋ธ์ ๊ฒฐ๊ณผ๊ฐ ์ค Num, next, nextAfter ์นผ๋ผ ๊ฐ์ด ๋ชจ๋ ์ผ์นํ๋ Num๊ฐ์ ์ฐพ์ผ๋ฉด ์ ์ด๋ 3๋ฒ ์ฐ์์ผ๋ก ๋์ค๋ ๋ฐ์ดํฐ๋ค์ ์ถ์ถํ๊ฒ ๋๋ค.
๋ค์์ LEAD() ๋ฅผ ์ฌ์ฉํ ์ฟผ๋ฆฌ๋ฌธ์ด๋ค.
-- LEAD๋ฅผ ์ฌ์ฉํ ํ์ด
SELECT DISTINCT sub.Num AS ConsecutiveNums
FROM (SELECT Num,
LEAD(Num, 1) OVER (ORDER BY Id) AS next,
LEAD(Num, 2) OVER (ORDER BY Id) AS nextAfter
FROM Logs) sub
WHERE sub.Num = sub.next AND sub.next = sub.nextAfter
LEAD๋ฅผ ์ํํ ์๋ธ์ฟผ๋ฆฌ์ ์ ํ ์ด๋ธ๋ก ๋ํ๋ด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
Id | Num | next | nextAfter |
1 | 1 | 1 | 1 |
2 | 1 | 1 | 2 |
3 | 1 | 2 | 1 |
4 | 2 | 1 | 2 |
5 | 1 | 2 | 2 |
6 | 2 | 2 | null |
7 | 2 | null | null |
# 184๋ฒ
184๋ฒ ๋ฌธ์ ์ ๋ฌธ์ ์์ ์๊ตฌํ๋ ํํ๋ฅผ ์ดํด๋ณด์.
Write a SQL query to find employees who have the highest salary in each of the departments. For the above tables, your SQL query should return the following rows (order of rows does not matter).
(๊ฐ ๋ถ์์ ๊ฐ์ฅ ๋์ ๋ด๊ธ์ ๋ฐ๋ ์ง์๋ค์ ์ฟผ๋ฆฌํด๋ผ. ๋จ ์ถ๋ ฅ๋๋ ๋ฐ์ดํฐ์ ์ ๋ ฌ ๊ธฐ์ค์ ์๊ด์ด ์๋ค.)
์ด๋ฒ ๋ฌธ์ ๋ Window Function์ ์ฌ์ฉํ์ง ์๊ณ ์ผ๋ฐ์ ์ธ ์ฟผ๋ฆฌ๋ฌธ๊ณผ Window Function ์ค ์ง๊ณํจ์์ธ MAX() ๋ฅผ ์ฌ์ฉํด ํด๊ฒฐํ๋ 2๊ฐ์ง ๋ฐฉ๋ฒ์ด ์๋ค. ์ฐ์ ์ผ๋ฐ ์ฟผ๋ฆฌ๋ฌธ ํ์ด๋ ๋ค์๊ณผ ๊ฐ๋ค.
-- 1. ๋ถ์๋ณ ๊ฐ์ฅ ๋์ ๋ด๊ธ์ ์ฐ์ ์ฟผ๋ฆฌ
-- 2. 1๋ฒ ์ฟผ๋ฆฌํ ๊ฒฐ๊ณผ ํ
์ด๋ธ๊ณผ ๋ถ์์ด๋ฆ์ด ์ ํ์๋ Department ํ
์ด๋ธ ์กฐ์ธ
-- 3. 2๋ฒ์์ ์กฐ์ธํ ํ
์ด๋ธ์ Employee ํ
์ด๋ธ๊ณผ DepartmentId ๊ธฐ์ค์ผ๋ก ์กฐ์ธ
-- 4. Employee์ Salary(์ง์๋ค์ด ๋ฐ์ ๋ด๊ธ)๊ณผ max_Salary(๋ถ์๋ณ ์ต๋ ๋ด๊ธ)์ด ๊ฐ์ ๋ฐ์ดํฐ ์ฟผ๋ฆฌ
-- ์ผ๋ฐ ์ฟผ๋ฆฌ
SELECT sub2.Name AS Department, e.Name AS Employee, e.Salary
FROM Employee AS e
INNER JOIN (SELECT *
FROM (SELECT DepartmentId, MAX(Salary) AS max_Salary
FROM Employee
GROUP BY DepartmentId) sub1
INNER JOIN Department AS d ON sub1.DepartmentId = d.Id) sub2 ON e.DepartmentId = sub2.DepartmentId
WHERE e.Salary = sub2.max_Salary
์ฟผ๋ฆฌ๋ฌธ์ ์์ฑํ ๋ ๊ณ ๋ คํ ์ฌํญ์ ์์ฐจ์ ์ผ๋ก ์ด๋ป๊ฒ ๊ตฌ์ํ๋์ง ์ ์ฝ๋์ ์ฃผ์์ผ๋ก ์์ฑํด๋ณด์๋ค. ์๋ธ์ฟผ๋ฆฌ ํ๋์ฉ ์ผ์ผ์ด ๊ฒฐ๊ณผํ๋ฉด์ ๊ด์ฐฐํ๋ฉด ์ดํด๊ฐ ์์ํ ๊ฒ์ด๋ค.
๋ค์์ Window Function ์ MAX() ๋ฅผ ์ฌ์ฉํ ํ์ด์ด๋ค. ์๋ ์ฝ๋๋ฅผ ๋ณด๋ฉด Window Function ๊ตฌ๋ฌธ์ ์ฌ์ฉํจ์ผ๋ก์จ ์๋ธ์ฟผ๋ฆฌ๊ฐ 1๊ฐ ๊ฐ์ํ๋ ์ฝ๋์ ๊ฐ๊ฒฐ์ฑ์ด ํฅ์๋์์์ ๋ณผ ์ ์๋ค.
-- 1.์ฐ์ ๋ถ์ id - ๋ถ์์ด๋ฆ ๋งค์นญ์ํค๊ธฐ ์ํด ๋ ๊ฐ์ ํ
์ด๋ธ ์กฐ์ธ
-- 2.์๋์ฐ ํ์
์ฌ์ฉํด์ ๋ถ์๋ณ ์ต๊ณ ๋ด๊ธ ํ
์ด๋ธ ๋ง๋ค๊ธฐ
-- 3.2๋ฒ ๊ฒฐ๊ณผ ํ
์ด๋ธ์ Employee ํ
์ด๋ธ๊ณผ ์กฐ์ธ์ํค๊ธฐ
-- 4.๋ด๊ธ๊ณผ ์ต๋๋ด๊ธ์ด ๊ฐ์ ๋ฐ์ดํฐ ์ฟผ๋ฆฌ
-- Window Function ์ฌ์ฉ - ๋ถ์๋ณ ~ ์ต๋๋ด๊ธ
SELECT sub.Department, E.name AS Employee, E.Salary
FROM Employee AS E
INNER JOIN (SELECT DISTINCT d.Id AS DepartmentId, d.name AS Department, MAX(Salary) OVER (PARTITION BY DepartmentId) AS max_Salary
FROM Employee AS e
INNER JOIN Department AS d ON e.DepartmentId = d.Id) sub ON E.DepartmentId = sub.DepartmentId
WHERE E.Salary = sub.max_Salary
# 185๋ฒ
๋ค์์ 185๋ฒ์ ๋ฌธ์ ์ ์๊ตฌํ๋ ์ถ๋ ฅ ํํ๋ฅผ์ดํด๋ณด์.
Write a SQL query to find employees who earn the top three salaries in each of the department. For the above tables, your SQL query should return the following rows (order of rows does not matter).
(๊ฐ ๋ถ์๋ณ๋ก ๊ฐ์ฅ ๋์ ์์ ๋ด๊ธ 3๋ฒ์งธ ๊น์ง ๋ฐ๋ ์ง์๋ค์ ์ฟผ๋ฆฌํด๋ผ. ์ถ๋ ฅ๊ฒฐ๊ณผ์ ๋ฐ์ดํฐ ์์๋ ์๊ด์ด ์๋ค.
ํด๋น ๋ฌธ์ ๋ฅผ ํ๊ธฐ ์ํด์๋ Window Function ์ค DENSE_RANK() ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ๋งค์ฐ ์ ์ฉํ๋ค. DENSE_RANK()๋ ํน์ ๊ฐ์ ๊ธฐ์ค์ผ๋ก ๋ด๋ฆผ(๋๋ ์ค๋ฆ) ์ฐจ์์ผ๋ก ์ ๋ ฌ ํ ์์๋ฅผ ๋ถ์ฌํ๋ ํจ์์ธ๋ฐ, DENSE_RANK() ์ด์ธ์ ROW_NUMBER(), RANK() ํจ์๋ ์๋๋ฐ, ๊ฐ๋จํ๊ฒ ์ด 3๊ฐ์ง์ ์ฐจ์ด์ ์ ๋ํด ์ดํด๋ณด์. ์๋ฅผ ๋ค์ด ๋ง์ฝ ๋ค์๊ณผ ๊ฐ์ ํ ์ด๋ธ์ด ์๋ค๊ณ ๊ฐ์ ํ์.
Name | Level |
John | 154 |
Mike | 122 |
Eliot | 122 |
Sara | 115 |
Laura | 200 |
์ ํ ์ด๋ธ์์ 3๊ฐ์ง ํจ์๋ฅผ ์ ์ฉํ ๊ฐ๊ฐ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค. ์ฐธ๊ณ ๋ก Level์ ๊ธฐ์ค์ผ๋ก ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌํ๋ค๋ ๊ฐ์ ํ๊ฒ ROW_NUMBER(), RANK(), DENSE_RANK()๋ฅผ ์ฌ์ฉํด ๋ง๋ ํ์๋ณ์๋ค์ ๋ค์๊ณผ ๊ฐ์์ง๋ค.
Name | Level | ROW_NUMBER() | RANK() | DENSE_RANK() |
Laura | 200 | 1 | 1 | 1 |
John | 154 | 2 | 2 | 2 |
Mike | 122 | 3 | 3 | 3 |
Eliot | 122 | 4 | 3 | 3 |
Sara | 115 | 5 | 5 | 4 |
์ด์ ์ด๋ค ๊ฐ๋ ์ธ์ง ํผ๋ถ์ ํ ์๋ฟ์ ๊ฒ์ด๋ค. ๊ทธ๋ผ ์ด์ ์ด๋ฅผ ํ์ฉํด 185๋ฒ ๋ฌธ์ ๋ฅผ ํ์ดํ SQL ๊ตฌ๋ฌธ์ ๋ค์๊ณผ ๊ฐ๋ค.
-- 1.์ฐ์ ๋ถ์id, ๋ถ์์ด๋ฆ ๋งค์นญ์ํค๊ธฐ
-- 2.๋ถ์๋ณ ๋ด๊ธ ์์ผ๋ก ๋์ค๋ญํฌ ์ ๋ ฌํ ํ
์ด๋ธ ๋ง๋ค๊ธฐ
-- 3.2๋ฒ์์ ๋ง๋ ํ
์ด๋ธ์ FROM ์๋ธ์ฟผ๋ฆฌ๋ก ๋ฃ์ด์ฃผ๊ณ ์์๊ฐ 3์ ์ดํ์ธ ๋ฐ์ดํฐ๋ค๋ง ์ฟผ๋ฆฌ
-- ์ฐธ๊ณ ๋ก ์๋์ฐ ํ์
์ผ๋ก ๋ง๋ ๋ณ์๋ฅผ ์๋ก์ด ์นผ๋ผ์ผ๋ก ๋ค์ด๋ฐํด์ค๋๋ '' ๋ฐ์ดํ ๋ถ์ฌ์ฃผ์ด์ผ ํจ!!
SELECT sub.Department, sub.Employee, sub.Salary
FROM (SELECT d.Name AS Department,
e.Name AS Employee,
e.Salary AS Salary,
DENSE_RANK() OVER (PARTITION BY d.Name ORDER BY e.Salary DESC) AS 'Rank'
FROM Employee AS e
INNER JOIN Department AS d ON e.DepartmentId = d.Id) sub
WHERE sub.Rank <= 3
์์์ ์ฃผ์ํด์ผ ํ ๋ถ๋ถ(ํ์๋ ์ฒ์ ์์๋ค..)์ ๋ฐ๋ก DENSE_RANK()๋ก ๋ง๋ ์๋ก์ด ์นผ๋ผ์ ํ๋์ ์๋ก์ด ์ด๋ฆ์ผ๋ก ๋ค์ด๋ฐํด์ค ๋๋ ๋ฐ๋์ ' ' (๋ฐ์ดํ)๋ฅผ ๋ถ์ฌ์ผ ํ๋ค.(์๋ฐ์ดํ๋ ๊ฐ๋ฅํ๋ค)
DENSE_RANK() OVER (PARTITION BY columnA ORDER BY columnB DESC|ASC) AS 'New column name'
'SQL' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[SQL] Second Highest Salary(Leetcode - 176๋ฒ) (0) | 2021.02.02 |
---|---|
[SQL] HAVING, WHERE, FROM ์ ์ ์๋ธ์ฟผ๋ฆฌ ์ด์ฉํ๊ธฐ(HackerRank - Top Earners ๋ฌธ์ ) (0) | 2021.02.01 |
[SQL] MySQL - ๋๋ง์ Function ๋ง๋ค๊ธฐ(Leetcode - 177๋ฒ) (0) | 2021.01.29 |
[SQL] - Delete, Update๋ฌธ ์ฌ์ฉํ๊ธฐ(Leetcode - 196, 627๋ฒ) (0) | 2021.01.27 |
[SQL] MySQL - SET ๊ณผ ์๋ธ์ฟผ๋ฆฌ ์ฌ์ฉํ๊ธฐ (4) | 2021.01.26 |