SQL 코딩테스트 준비를 위해 해커랭크 문제풀이를 해보려고 합니다. 🔥 문제 분석을 통해 정답 SQL 쿼리와 오답을 포함한 자세한 풀이 과정을 작성했습니다.서버는 MySQL을 기준으로 설정하였으며, 문제의 핵심은 [WHERE 절의 서브쿼리 작성하는 법]을 이해하는 것입니다. SQL 코딩 능력을 키우고자 하는 분들에게 도움이 될 수 있도록 문제 해결에 필요한 사고 과정과 코드 설명을 상세히 다루었습니다.
문제 : Ollivander's Inventory (hackerrank sql)
난이도 : Medium -> 글쓴이 체감 난이도 : Hard
서버 : MySQL
테이블 이름 : Wands, Wands_Property
문제 의도 : non-evil의 각각 power, age에 대해 필요한 최소한의 gold galleons들의 데이터만 추출하는 것.
문제 요약 :
추출 - id, age, coins_needed, power
조건 - wands_property의 code와 age의 쌍이 일대일 관계. 즉, code와 age 모두 고유한 값을 가지고 있어야 함.
정렬 - power desc, age desc
조건 - non-evil? 한국어 뜻은 잘 몰랐지만..ㅎ 문제에서 조건상 non- evil은 is_evil = 0
input sample
output sample
정답 sql 코드 :
SELECT w.id, wp.age, w.coins_needed, w.power
FROM Wands w
JOIN Wands_Property wp ON w.code = wp.code
WHERE wp.is_evil = 0
AND w.coins_needed = (
SELECT MIN(w1.coins_needed)
FROM Wands w1
JOIN Wands_Property wp1 ON w1.code = wp1.code
WHERE wp.age = wp1.age
AND w.power = w1.power
)
ORDER BY w.power DESC, wp.age DESC;
sql 풀이과정 :
(나의 풀이 사고과정 정리)
일단, 간단하게 생각해서 age, power별로 coins_needed가 최소인 행만 추출하는 쿼리로 생각했다.
그러나, 이 쿼리는 wands_property의 code와 age의 쌍이 일대일 관계.
즉, code와 age 모두 고유한 값을 가지고 있어야 한다는 조건이 없기 떄문에, code가 겹치거나 age가 겹칠 가능성이 있다.
그러나 .. input, output example data만 생각하고 다음과 같은 쿼리 결과 code, age 모두 고유한 값인데 왜 오류가 나는지 몰랐다.
SELECT
wp.age,
MIN(w.coins_needed) AS min_coins_needed,
w.power
FROM
Wands w
JOIN
Wands_Property wp ON w.code = wp.code
WHERE
wp.is_evil = 0
GROUP BY
wp.age, w.power
ORDER BY
w.power DESC, wp.age DESC;
오류가 난 이유는...!!
Hackkerrank에서 문제예시로 보여주는 테이블은 정말 예시일뿐, 정답을 맞춰서 나오는 결과값들의 데이터는 훨씬 ~~ 더 많다는 사실!
따라서, 결과 테이블 값에서 겹치지 않더라도 저 조건이 들어가야 결과 테이블에서 age, code 모두 일대일 관계를 수립할 수 있다.
그래서,
서브쿼리를 사용해 code, age별 min(coin_needed)값 행에 맞는 행들만 가져오도록 해야한다
서브쿼리는 다음과 같이 실행하면
SELECT MIN(w1.coins_needed)
FROM Wands w1
JOIN Wands_Property wp1 ON w1.code = wp1.code
WHERE wp.age = wp1.age
AND w.power = w1.power
MIN(coins_needed) |
504 |
6773 |
5689 |
6020 |
따라서, 다음과 같은 코드를 실행하면 정답!
SELECT w.id, wp.age, w.coins_needed, w.power
FROM Wands w
JOIN Wands_Property wp ON w.code = wp.code
WHERE wp.is_evil = 0
AND w.coins_needed = (
SELECT MIN(w1.coins_needed)
FROM Wands w1
JOIN Wands_Property wp1 ON w1.code = wp1.code
WHERE wp.age = wp1.age
AND w.power = w1.power
)
ORDER BY w.power DESC, wp.age DESC;
그런데, 또 여기서 의문! 2가지가 들었다.
Q1. 위의 정답 코드의 서브쿼리에서 서브쿼리만 실행하면 나오는 결과물이 다중행인데, 비교연산자 (=)도 다중행일떄 사용할 수 있나?
보통 다중행은 IN, NOT IN이고 단일행은 (=, >, <)을 사용하는 줄 알았는데?
-> = 도 다중행 비교 가능!
MIN(coins_needed) |
504 |
6773 |
5689 |
6020 |
Q2. 그렇다면, where 서브쿼리절에 = 말고 IN이라면?
IN도 정답!