본문 바로가기

Query

[프로그래머스]상위 n개 레코드, 업그레이드 된 아이템 구하기

프로그래머스 SQL 고득점 Kit 문제

1. 상위 n개 레코드

2. 업그레이드 된 아이템 구하기


문제1. 상위 n개 레코드

https://school.programmers.co.kr/learn/courses/30/lessons/59405

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

더보기

문제 설명

ANIMAL_INS 테이블은 동물 보호소에 들어온 동물의 정보를 담은 테이블입니다. ANIMAL_INS 테이블 구조는 다음과 같으며, ANIMAL_ID, ANIMAL_TYPE, DATETIME, INTAKE_CONDITION, NAME, SEX_UPON_INTAKE는 각각 동물의 아이디, 생물 종, 보호 시작일, 보호 시작 시 상태, 이름, 성별 및 중성화 여부를 나타냅니다.


NAME  TYPE  NULLABLE
ANIMAL_ID VARCHAR(N) FALSE
ANIMAL_TYPE VARCHAR(N) FALSE
DATETIME DATETIME FALSE
INTAKE_CONDITION VARCHAR(N) FALSE
NAME VARCHAR(N) TRUE
SEX_UPON_INTAKE VARCHAR(N) FALSE

동물 보호소에 가장 먼저 들어온 동물의 이름을 조회하는 SQL 문을 작성해주세요.

예시

예를 들어 ANIMAL_INS 테이블이 다음과 같다면


ANIMAL_ID  ANIMAL_TYPE  DATETIME  INTAKE_CONDITION  NAME  SEX_UPON_INTAKE
A399552 Dog 2013-10-14 15:38:00 Normal Jack Neutered Male
A379998 Dog 2013-10-23 11:42:00 Normal Disciple Intact Male
A370852 Dog 2013-11-03 15:04:00 Normal Katie Spayed Female
A403564 Dog 2013-11-18 17:03:00 Normal Anna Spayed Female

이 중 가장 보호소에 먼저 들어온 동물은 Jack입니다. 따라서 SQL문을 실행하면 다음과 같이 나와야 합니다.

NAME
Jack

※ 보호소에 가장 먼저 들어온 동물은 한 마리인 경우만 테스트 케이스로 주어집니다.


본 문제는 Kaggle의 "Austin Animal Center Shelter Intakes and Outcomes"에서 제공하는 데이터를 사용하였으며 ODbL의 적용을 받습니다.


풀이

풀이 로직

1.) ORDER BY로 정렬한 이후, LIMIT함수로 상위 N개 추출

-- 코드를 입력하세요
SELECT
    NAME
FROM ANIMAL_INS 
ORDER BY DATETIME ASC 
LIMIT 1 ;

 결과

=>

NAME
Jack

윈도우 함수 연습

만약 ANIMAL_TYPE을 기준으로 행 번호 칼럼을 만들어주고 싶다면? 

-- 코드를 입력하세요
SELECT
    ROW_NUMBER() OVER (ORDER BY DATETIME) AS ROWNUMBER,
    NAME
FROM ANIMAL_INS 
LIMIT 1 
;

 결과

=> 


ROWNUMBER NAME
1 Jack

 

이런식으로도 접근을 할 수 있다. 


문제2. 업그레이드 된 아이템 구하기

https://school.programmers.co.kr/learn/courses/30/lessons/273711

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

더보기

문제 설명

 

어느 한 게임에서 사용되는 아이템들은 업그레이드가 가능합니다.

'ITEM_A'->'ITEM_B'와 같이 업그레이드가 가능할 때

'ITEM_A'를 'ITEM_B' 의 PARENT 아이템,

PARENT 아이템이 없는 아이템을 ROOT 아이템이라고 합니다.

 

예를 들어 'ITEM_A'->'ITEM_B'->'ITEM_C'와 같이 업그레이드가 가능한 아이템이 있다면

'ITEM_C'의 PARENT 아이템은 'ITEM_B'

'ITEM_B'의 PARENT 아이템은 'ITEM_A'

ROOT 아이템은 'ITEM_A'가 됩니다.

 

다음은 해당 게임에서 사용되는 아이템 정보를 담은 ITEM_INFO 테이블과 아이템 관계를 나타낸 ITEM_TREE 테이블입니다. ITEM_INFO 테이블은 다음과 같으며, ITEM_ID, ITEM_NAME, RARITY, PRICE는 각각 아이템 ID, 아이템 명, 아이템의 희귀도, 아이템의 가격을 나타냅니다.


Column name Type  Nullable
ITEM_ID INTEGER FALSE
ITEM_NAME VARCHAR(N) FALSE
RARITY INTEGER FALSE
PRICE INTEGER FALSE

ITEM_TREE 테이블은 다음과 같으며, ITEM_ID, PARENT_ITEM_ID는 각각 아이템 ID, PARENT 아이템의 ID를 나타냅니다.


Column name Type  Nullable
ITEM_ID INTEGER FALSE
PARENT_ITEM_ID INTEGER TRUE

단, 각 아이템들은 오직 하나의 PARENT 아이템 ID를 가지며, ROOT 아이템의 PARENT 아이템 ID는 NULL 입니다.

ROOT 아이템이 없는 경우는 존재하지 않습니다.


문제

아이템의 희귀도가 'RARE'인 아이템들의 모든 다음 업그레이드 아이템의 아이템 ID(ITEM_ID), 아이템 명(ITEM_NAME), 아이템의 희귀도(RARITY)를 출력하는 SQL 문을 작성해 주세요. 이때 결과는 아이템 ID를 기준으로 내림차순 정렬주세요.


예시

예를 들어 ITEM_INFO 테이블이 다음과 같고


ITEM_ID  ITEM_NAME  RARITY  PRICE
0 ITEM_A RARE 10000
1 ITEM_B RARE 9000
2 ITEM_C LEGEND 11000
3 ITEM_D RARE 10000
4 ITEM_E RARE 12000

ITEM_TREE 테이블이 다음과 같다면


ITEM_ID  PARENT_ITEM_ID
0 NULL
1 0
2 0
3 1
4 1

아이템의 희귀도가 'RARE'인 아이템은 'ITEM_A', 'ITEM_B', 'ITEM_D', 'ITEM_E' 입니다.

이 중 'ITEM_A' 는 'ITEM_B', 'ITEM_C' 로 업그레이드가 가능하며 'ITEM_B' 는 'ITEM_D' , 'ITEM_E' 로 업그레이드가 가능합니다. 'ITEM_D' 와 'ITEM_E'는 더 이상 업그레이드가 가능하지 않습니다. 따라서 결과는 다음과 같이 나와야 합니다.


ITEM_ID  ITEM_NAME  RARITY
4 ITEM_E RARE
3 ITEM_D RARE
2 ITEM_C LEGEND
1 ITEM_B RARE

※ 참고: 본 문제는 제출 내역 확인 기능을 지원하지 않습니다.


풀이

이 문제는 이해하기가 되지 않아서, 5번 정도 읽었던 것 같다. 

게임을 하는 입장에서 아이템 업그레이드가 A등급이 가장 좋다고 생각이 들어서 계속 헷갈렸던 것 같다 ㅋㅋ

 

중요하진 않지만, 이 문제에선 A → B → C → D 등급으로 좋아진다고 생각하면 된다. 

 

또한, ITEM_INFO와 ITEM_TREE 에는 다음 업그레이드될 아이템은 나와있지 않다.

두 DB를 통해서, 업그레이될 수 있는 쌍을 유추해야 한다.

 

 

(현재 아이템, 다음에 업그레이드 될 쌍)은 두 DB를 통해 (업그레이드 되기 전 아이템, 업글 된 현재 아이템)을 활용하여 유추해야 한다.  [ 칼럼명으로 (PARENT_ITEM_ID, ITEM_NAME)  ]

 

(현재 아이템, 다음에 업그레이드 될 쌍) →  (PARENT_ITEM_ID, ITEM_NAME)

 (참조  [STEP1, STEP2 참고 사진]  ) 

 

결과로는 다음에 업그레이될 아이템 정보를 추출해야 한다. 

 

로직

STEP 1.) ITEM_INFO와 ITEM_TREE를 JOIN. 

  1. INNER JOIN 
  2. 유추할 쌍은 무조건 있어야 하기 때문에, WHERE PARENT_ITEM_ID IS NOT NULL 조건 추가

STEP  2.) JOIN한 DB에서 PARENT_ITEM_ID들이 ITEM_INFO에서 RARITY값이 RARE인 ITEM_ID에 포함되어 있는 것들만 추출

 

 [STEP1, STEP2 참고 사진]

STEP  3.) 정렬 / 추출

 

 

코드는 다음과 같다. 

SELECT # STEP3.) 정렬 / 추출
    ITEM_ID, ITEM_NAME, RARITY
FROM (
    SELECT # STEP1.) ITEM_INFO와 ITEM_TREE를 JOIN. 
        I.ITEM_ID, I.ITEM_NAME, I.RARITY, T.PARENT_ITEM_ID
    FROM ITEM_INFO I 
        INNER JOIN ITEM_TREE T
        ON I.ITEM_ID = T.ITEM_ID
    WHERE T.PARENT_ITEM_ID IS NOT NULL ) JOIN_TABLE
WHERE PARENT_ITEM_ID IN ( # STEP2.) JOIN한 DB에서 PARENT_ITEM_ID들이 ITEM_INFO에서 RARITY값이 RARE인 ITEM_ID에 포함되어 있는 것들만 추출
    -- 조건 만들어주기
    SELECT 
        ITEM_ID
    FROM ITEM_INFO
    WHERE RARITY = 'RARE'
)
ORDER BY ITEM_ID DESC 
;

 

 

좋은 성과를 얻으려면 한 걸음 한 걸음이 힘차고 충실하지 않으면 안 된다

-단테-