https://www.hackerrank.com/challenges/harry-potter-and-wands/problem?isFullScreen=true
코드설명
INNER JOIN + SUBQUERY + MIN 을 활용합니다.
상당히 어려운 문제라고 느꼈습니다.
문제에서 요지는 이렇습니다.
OLIVANDER의 장비창에는 완드들이 존재합니다.
여기서 우리는 CODE, POWER 별로 COINS_NEEDED가 가장 작은 WANDS를 구해서 리스트로 보여주는 것입니다. 이때 부가적으로 완드가 EVIL 한지, 그리고 AGE 출력과 정렬을 위해 WANDS_PROPERTY와 INNER JOIN 해둡니다.
처음에 저는 아래와 같이 접근했습니다. 틀린코드입니다.
SELECT W.CODE, MIN(W.COINS_NEEDED), W.POWER
FROM WANDS W
INNER JOIN WANDS_PROPERTY WP
ON W.CODE = WP.CODE
AND WP.IS_EVIL = 0
GROUP BY W.CODE, W.POWER
ORDER BY W.POWER DESC, MIN(WP.AGE) DESC;
W.CODE와 W.POWER별로 가장 저렴한 완드 리스트를 출력하는 것이었기에, W.CODE와 W.POWER로 GROUP BY 하고, WANDS와 WANDS_PROPERTY 는 M:1 관계이기에 MIN(W.COINS_NEEDED)로 M 쪽의 최소값을 가져오면 코인의 최소값을 가져올려고 했습니다. 하지만, 이 방법에서의 문제점은 WANDS_PROPERTY의 값들을 가져오지 못한다는 점입니다.
ORACLE 코드
정답코드1입니다.
상관서브쿼리를 활용해서 NESTED LOOP 방식으로 각 CODE와 POWER당 최소 값을 가져옵니다.
SELECT W.ID, WP.AGE, W.COINS_NEEDED, W.POWER
FROM WANDS W
INNER JOIN WANDS_PROPERTY WP
ON W.CODE = WP.CODE
WHERE WP.IS_EVIL = 0
AND W.COINS_NEEDED = (SELECT MIN(COINS_NEEDED) FROM WANDS W2 WHERE W2.CODE = W.CODE AND W2.POWER = W.POWER)
ORDER BY W.POWER DESC, WP.AGE DESC;