๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

SQL

[SQL] MySQL - ๋‚˜๋งŒ์˜ Function ๋งŒ๋“ค๊ธฐ(Leetcode - 177๋ฒˆ)

๋ฐ˜์‘ํ˜•

๐Ÿ”Š ๋ณธ ํฌ์ŠคํŒ…์—์„œ ์‚ฌ์šฉ๋˜๋Š” ํ…Œ์ด๋ธ”์˜ ์ž๋ฃŒ์™€ ์ถœ์ฒ˜๋Š” Leetcode์ž„์„ ๋ฐํž™๋‹ˆ๋‹ค. ๋” ๋‹ค์–‘ํ•œ SQL ๋ฌธ์ œ๋ฅผ ํ’€์–ด๋ณด์‹œ๋ ค๋ฉด Leetcode ์‚ฌ์ดํŠธ๋ฅผ ๋ฐฉ๋ฌธํ•ด ๋ณด์„ธ์š”!

 

LeetCode ์‚ฌ์ดํŠธ

 

์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” SQL๋„ Python๊ณผ ๊ฐ™์€ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋“ค์ฒ˜๋Ÿผ ์‚ฌ์šฉ์ž ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ณ  ์ด๋ฅผ ์ด์šฉํ•ด ๋ฌธ์ œ๋ฅผ ํ’€์–ด๋ณด๋ ค ํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” MySQL ๊ธฐ์ค€์œผ๋กœ์˜ ์‚ฌ์šฉ์ž ํ•จ์ˆ˜ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ๋งŒ ์†Œ๊ฐœํ•œ๋‹ค. ์šฐ์„  MySQL๋กœ ์‚ฌ์šฉ์ž ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“œ๋Š” ๊ตฌ์กฐ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž.

 

MySQL ํ•จ์ˆ˜ ๋งŒ๋“œ๋Š” ๊ตฌ์กฐ

 

์œ„์™€ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ๊ฐ„๋‹จํžˆ ์„ค๋ช…ํ•˜๋ฉด CREATE FUNCTION~ ์ฒซ ๋ฒˆ์งธ RETURNS ๋ถ€๋ถ„์€ ์ธํ’‹ ๋ณ€์ˆ˜์™€ ์•„์›ƒํ’‹์œผ๋กœ ๋‚ด๋ฑ‰์„ ๊ฐ’์˜ type์„ ์ •ํ•˜๋Š” ๋ถ€๋ถ„์ด๋ฉฐ BEGIN ~ END ์‚ฌ์ด์—๋Š” ์ถœ๋ ฅ๊ฐ’์„ ๋‚ด๋ฑ‰๊ธฐ ์œ„ํ•œ ์—ฐ์‚ฐ๊ณผ ๋ณ€์ˆ˜๋ฅผ ํ• ๋‹นํ•˜๋Š” ๋ถ€๋ถ„์ด๋ผ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ตฌํ˜„ํ•ด์•ผ ํ• ๋•Œ ์ฃผ์˜ํ•ด์•ผ ํ•  ์ ์€ ๋‘ ๊ฐ€์ง€์ด๋‹ค.(ํ•„์ž๊ฐ€ ์ž์ฃผํ•˜๋Š” ์‹ค์ˆ˜๋‹ค..)

 

  1. ์ฒซ ๋ฒˆ์งธ๋Š” RETURNS ์ด๊ณ  ๋‘ ๋ฒˆ์งธ๋Š” RETURN ์ด๋‹ค! S์˜ ์œ ๋ฌด๋ฅผ ์ฃผ์˜ํ•˜์ž.
  2. ๋‹ค๋ฅธ ๋ถ€๋ถ„์—๋Š” ์„ธ๋ฏธ์ฝœ๋ก (;)์„ ์•ˆ ๋ถ™์—ฌ๋„ ๋˜์ง€๋งŒ ๋นจ๊ฐ„์ƒ‰์œผ๋กœ ํ‘œ๊ธฐ๋œ ๋ถ€๋ถ„(๋ณ€์ˆ˜๋ฅผ ํ• ๋‹นํ•˜๊ณ  ์ฟผ๋ฆฌ๋กœ ์•„์›ƒํ’‹์„ return ํ•˜๋Š” ๋ถ€๋ถ„)์€ ๋ฌด์กฐ๊ฑด ์„ธ๋ฏธ์ฝœ๋ก (;)์„ ์ ์–ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

์ž, ์ด์ œ Leetcode์˜ 177๋ฒˆ ๋ฌธ์ œ๋ฅผ ์‚ฌ์šฉ์ž ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•ด์„œ ํ’€์ดํ•ด๋ณด์ž. ์šฐ์„  ๋ฌธ์ œ์™€ ์›ํ•˜๋Š” ํ˜•ํƒœ์˜ ์ถœ๋ ฅ ํฌ๋งท์„ ํ™•์ธํ•ด๋ณด์ž.

 

Write a SQL query to get the nth highest salary from the Employee table.
(Employee ํ…Œ์ด๋ธ”์—์„œ n๋ฒˆ์งธ๋กœ ๊ฐ€์žฅ ๋งŽ์€ salary๋ฅผ ์ถœ๋ ฅํ•ด๋ผ. ์ด ๋•Œ ๋งŒ์•ฝ n๋ฒˆ์งธ ๊ฐ€์žฅ ๋งŽ์€ salary๊ฐ’์ด ์—†๋‹ค๋ฉด null๊ฐ’์„ ์ถœ๋ ฅ์‹œ์ผœ๋ผ.)

 

๋ฌธ์ œ์—์„œ ์š”๊ตฌํ•˜๋Š” ์ถœ๋ ฅ ํ˜•ํƒœ

 

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ ํฐ ํ‹€์€ ์‚ฌ์šฉ์ž ์ •์˜ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ’€์ดํ•˜์ง€๋งŒ ํ•จ์ˆ˜ ๋‚ด๋ถ€์ ์œผ๋กœ ํ’€์ด๋ฐฉ๋ฒ•์ด 3๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค. ์ด๋ฅผ ํ•˜๋‚˜์”ฉ ์†Œ๊ฐœํ•ด๋ณธ๋‹ค.

 

1. LIMIT ๊ณผ OFFSET ํ™œ์šฉํ•˜๊ธฐ

์šฐ์„  LIMIT๊ณผ OFFSET์— ๋Œ€ํ•œ ๊ฐœ๋…์„ ๋ชจ๋ฅธ๋‹ค๋ฉด ์—ฌ๊ธฐ๋ฅผ ์ฐธ์กฐํ•˜์ž. ์ด ํฌ์ŠคํŒ…์—์„œ๋Š” ์˜ˆ์‹œ ์ฟผ๋ฆฌ๋ฌธ ํ•˜๋‚˜๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ฐœ๋…์„ ์งš๊ณ  ๋„˜์–ด๊ฐ€์ž.

SELECT Salary FROM Employee ORDER BY Salary DESC LIMIT 2, 3

์œ„ ์ฟผ๋ฆฌ๋ฅผ ํ•ด์„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. Employee ํ…Œ์ด๋ธ”์—์„œ Salary๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋‚ด๋ฆผ์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•œ ํ›„ ์ƒ์œ„ 2๋ฒˆ์งธ ์ดํ›„์˜ ์ƒ์œ„ 3๊ฐœ ๊ฐ’. ๋งŒ์•ฝ [1, 2, 3, 4, 5, 6, ..] ์ˆœ์„œ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋‹ค๋ฉด ์œ„ ์ฟผ๋ฆฌ๋Š” 3, 4, 5 ๋ฒˆ์งธ ๋ฐ์ดํ„ฐ๋ฅผ ์ถœ๋ ฅ์‹œํ‚จ๋‹ค.

 

SELECT Salary FROM Employee ORDER BY Salary DESC LIMIT 3 OFFSET 2

 

์ด ์ฟผ๋ฆฌ๋Š” OFFSET๊ณผ LIMIT์„ ๊ฒฐํ•ฉํ•˜์—ฌ ์œ„์˜ ์ฟผ๋ฆฌ์™€ ๋™์ผํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅ์‹œํ‚จ๋‹ค. ์ถ”๊ฐ€๋กœ OFFSET์€ ์ธ์ž๋กœ ํฐ ์ˆซ์ž๋ฅผ ๋„ฃ์„์ˆ˜๋ก ์ฟผ๋ฆฌ ํผํฌ๋จผ์Šค๊ฐ€ ๋–จ์–ด์ง„๋‹ค๋Š” ์ ์„ ์ฐธ๊ณ ํ•˜์ž. ์˜ˆ๋ฅผ ๋“ค์–ด ์ƒ์œ„ 100๋ฒˆ์งธ ์ดํ›„์˜ ์ƒ์œ„ 3๊ฐœ์˜ ๊ฐ’์„ ์ถ”์ถœํ•˜๋ ค ํ•œ๋‹ค๋ฉด

 

LIMIT 3 OFFSET 100 ์ด ์•„๋‹Œ  LIMIT 100, 3์„ ์‚ฌ์šฉํ•˜๋„๋ก ํ•˜์ž.

์ด์ œ LIMIT๊ณผ OFFSET์„ ํ™œ์šฉํ•ด 177๋ฒˆ ๋ฌธ์ œ๋ฅผ ํ’€์–ด๋ณด์ž.

 

CREATE FUNCTION getNthHighestSalary (N INT)
        RETURNS INT
BEGIN
     DECLARE A INT;
     SET A = N-1;
     RETURN (SELECT Salary
             FROM Employee
             ORDER BY Salary DESC
             LIMIT 1 OFFSET A);
END

 

์—ฌ๊ธฐ์„œ ์˜๋ฌธ์ด ๋“ค ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์€ ์™œ ๊ตณ์ด A๋ฅผ N-1๋กœ ์ƒˆ๋กœ์šด ๋ณ€์ˆ˜๋ฅผ ํ• ๋‹นํ–ˆ๋ƒ๋Š” ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ํ•œ ์ด์œ ๋Š” ์‚ฌ์šฉ์žํ•จ์ˆ˜์˜ ์ธํ’‹ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๊ณ  ์žˆ๋Š” N์„ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์ƒˆ๋กœ์šด ๋ณ€์ˆ˜๋ฅผ ํ• ๋‹นํ•˜์ง€ ์•Š๊ณ  N-1 ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 

 

๊ทธ๋ฆฌ๊ณ  N๋ฒˆ์งธ ์ƒ์œ„์˜ ๊ฐ’์ด ์—†๋‹ค๋ฉด Null์„ ๋ฐ˜ํ™˜ํ•˜๋ผ๊ณ  ํ–ˆ๋Š”๋ฐ, LIMIT ๊ณผ OFFSET์€ ํ•ด๋‹น ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๊ฐ’์ด ์—†๋‹ค๋ฉด ์ž๋™์œผ๋กœ Null์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ์œ„ํ•ด ๋”ฐ๋กœ ์ฒ˜๋ฆฌํ•ด์ค„ ํ•„์š”๋Š” ์—†๋‹ค.

2. CASE WHEN๊ณผ ์„œ๋ธŒ์ฟผ๋ฆฌ ์‚ฌ์šฉํ•˜๊ธฐ

CASE WHEN์„ ์‚ฌ์šฉํ•ด๋ณผ ์ˆ˜ ๋„ ์žˆ๋‹ค. ๋‹ค์Œ SQL ๊ตฌ๋ฌธ์„ ๋ณด์ž.

 

CREATE FUNCTION getNthHighestSalary (N INT)
        RETURNS INT
BEGIN
     RETURN (SELECT CASE WHEN COUNT(sub.Salary) < N 
                          THEN Null
                          ELSE MIN(sub.Salary)
                          END
              FROM (SELECT DISTINCT Salary
                    FROM Employee
                    ORDER BY Salary DESC
                    LIMIT N) sub);
END

 

3. IF์™€ ์„œ๋ธŒ์ฟผ๋ฆฌ ์‚ฌ์šฉํ•˜๊ธฐ

2๋ฒˆ ํ’€์ด๋ฐฉ๋ฒ•์—์„œ CASE WHEN ๊ตฌ๋ฌธ์„ IF ๊ตฌ๋ฌธ์œผ๋กœ ๋ฐ”๊พธ์–ด ์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.

 

CREATE FUNCTION getNthHighestSalary (N INT)
        RETURNS INT
BEGIN
     RETURN (SELECT IF(COUNT(sub.Salary) < N, Null, MIN(sub.Salary))
              FROM (SELECT DISTINCT Salary
                    FROM Employee
                    ORDER BY Salary DESC
                    LIMIT N) sub);
END

 

์ด์ œ ๋ชจ๋“  ํ’€์ด๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์•˜๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์ง์ ‘ ์ •์˜ํ•ด์ค€ ํ•จ์ˆ˜๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ• ๊นŒ? ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.(ํ•ด๋‹น ๋ฆฌํŠธ์ฝ”๋“œ ๋ฌธ์ œ์—์„œ๋Š” ํ•จ์ˆ˜ ์ฟผ๋ฆฌ๋ฌธ๋งŒ ์ œ์ถœํ•˜๋ฉด ํ†ต๊ณผ๋œ๋‹ค)

 

-- ์ƒ์œ„ 10๋ฒˆ์งธ๋กœ ๋†’์€ Salary๋ฅผ ์ถœ๋ ฅํ•˜๊ธฐ!
SELECT getNthHighestSalary(10)
FROM Employee

 

๋ฐ˜์‘ํ˜•