https://school.programmers.co.kr/learn/courses/30/lessons/273711
코드설명
INNER JOIN + NESTED SUBQUERY + IN 을 활용합니다.
문제이해가 상당히 어렵습니다.
로직을 간단히 설명하겠습니다.
1. ITEM_INFO와 ITEM_TREE를 INNER JOIN 하여, 아래와 같은 구조를 만들어줍니다.
ITEM_ID ITEM_NAME RARITY PRICE ITEM_ID PARENT_ITEM_ID
0 | ITEM_A | RARE | 10000 | 0 | null |
1 | ITEM_B | RARE | 9000 | 1 | 0 |
2 | ITEM_C | LEGEND | 11000 | 2 | 0 |
3 | ITEM_D | RARE | 10000 | 3 | 1 |
4 | ITEM_E | RARE | 12000 | 4 | 1 |
왜 위와 같은 JOIN을 할까요?
ITEM_TREE의 COLUMN 값은 ITEM_ID와 PARENT_ITEM_ID 로 이루어져있습니다. 즉, ITEM_ID와 데이터가 연관되어있다는 것 입니다.
만약, ITEM_TREE의 값에 추가적인 COLUMN 들이 존재한다고 하면 어떻게 할것인가? 라는 고민이 생길 수 있습니다.
해당 부분은 문제 조건에서, 각 아이템들은 "단, 각 아이템들은 오직 하나의 PARENT 아이템 ID를 가지며, ROOT 아이템의 PARENT 아이템 ID는 NULL 입니다." 라는 조건이 있습니다.
알고리즘으로 따지자면, 단순 TREE 입니다.
2.. 위의 INNER JOIN을 통해 데이터를 만들었다면, PARENT_ITEM_ID가 'RARE'인 것을 골라내야 합니다.
WHERE절에 SUBQUERY가 존재하는 NESTED SUBQUERY 를 활용하여, 해당사항을 해결합니다.
매번, 하나의 레코드가 만들어질떄마다 서브쿼리가 실행된다는 점이 비효율적으로 보이나, 다른 방법으로도 이 방법은 피할 수 없는 방법으로 보입니다.
아래와 같이 현재 레코드의 PARENT_ITEM_ID가 ITEM_ID인것을 찾아서 RARITY가 'RARE'인 것을 찾아나갑니다.
WHERE
IT1.PARENT_ITEM_ID =
( SELECT ITEM_ID FROM ITEM_INFO WHERE ITEM_ID = IT1.PARENT_ITEM_ID AND RARITY = 'RARE')
이때 IN을 활용할 수도 있습니다. PARENT_ITEM_ID IN ( RARE인 아이템들의 ITEM_ID) 을 통하여서 ITEM_TREE에 주어진 각 ITEM들 중 부모가 RARE인것을 가져올 수 있습니다.
EQUAL(=)로 해도 됩니다.
PARENT_ITEM_ID가 NULL인 아이템은 ROOT 아이템으로써, 시작점이기에 무시됩니다.
코드
SELECT ITEM_INFO.ITEM_ID, ITEM_INFO.ITEM_NAME, ITEM_INFO.RARITY
FROM ITEM_INFO
INNER JOIN ITEM_TREE
ON ITEM_INFO.ITEM_ID = ITEM_TREE.ITEM_ID
WHERE ITEM_TREE.PARENT_ITEM_ID IN ( SELECT ITEM_ID FROM ITEM_INFO WHERE RARITY = 'RARE' )
ORDER BY ITEM_INFO.ITEM_ID DESC;
INLINE-VIEW 안의 쿼리를 좀 더 특정시켰습니다. (ITEM_ID = IT1.PARENT_ITEM_ID)
SELECT
II1.ITEM_ID AS ITEM_ID,
II1.ITEM_NAME AS ITEM_NAME,
II1.RARITY AS RARITY
FROM ITEM_INFO AS II1
INNER JOIN ITEM_TREE AS IT1
ON II1.ITEM_ID = IT1.ITEM_ID
WHERE
IT1.PARENT_ITEM_ID =
( SELECT ITEM_ID FROM ITEM_INFO WHERE ITEM_ID = IT1.PARENT_ITEM_ID AND RARITY = 'RARE')
ORDER BY IT1.ITEM_ID DESC
3중 INNER JOIN문으로 푼 코드입니다.
SELECT II2.ITEM_ID, II2.ITEM_NAME, II2.RARITY
FROM ITEM_INFO AS II
INNER JOIN ITEM_TREE AS IT
ON II.ITEM_ID = IT.PARENT_ITEM_ID
INNER JOIN ITEM_INFO AS II2
ON II2.ITEM_ID = IT.ITEM_ID
WHERE II.RARITY = 'RARE'
ORDER BY II2.ITEM_ID DESC