소피it블로그

[SQL] 프로그래머스 SQL 고득점 Kit -JOIN (MySQL) 본문

CS/데이터베이스

[SQL] 프로그래머스 SQL 고득점 Kit -JOIN (MySQL)

sophie_l 2022. 11. 4. 23:28

https://school.programmers.co.kr/learn/courses/30/parts/17046

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

1. 주문량이 많은 아이스크림들 조회하기

SELECT A.FLAVOR
FROM FIRST_HALF A
JOIN (SELECT FLAVOR, SUM(TOTAL_ORDER) TOTAL_ORDER
     FROM JULY
     GROUP BY FLAVOR) B
ON A.FLAVOR = B.FLAVOR
ORDER BY (A.TOTAL_ORDER + B.TOTAL_ORDER) DESC
LIMIT 3

차근차근 풀면 어렵지 않다.

8번을 풀고 와서 풀었기 때문에, JOIN문 뒤에 SELECT FLAVOR, SUM(TOTAL_ORDER)이 오며 SUM에는 alias를 붙여줘야 한다는 것, 그리고 GROUP BY FLAVOR로 묶어줘야 한다는 것은 쉽게 파악했다.

나머지는 문제에서 물어본 대로 구현만 하면 된다.

ORDER BY에 저렇게 식을 써도 된다는 것은 처음 알았다.

 

2. 그룹별 조건에 맞는 식당 목록 출력하기

-- 실패한 코드
SELECT A.MEMBER_NAME, B.REVIEW_TEXT, B.REVIEW_DATE
FROM MEMBER_PROFILE A
JOIN (SELECT *, COUNT(REVIEW_ID) COUNT
     FROM REST_REVIEW
     GROUP BY MEMBER_ID
     ORDER BY COUNT DESC
     LIMIT 1) B
ON A.MEMBER_ID = B.MEMBER_ID
ORDER BY B.REVIEW_DATE, B.REVIEW_TEXT

실패한 코드이다. 다른 분들 코드를 대충 보니 JOIN이 두 번 들어가는 것 같던데, 이런 경우는 처음이라 당황하였다.

다시 도전해봐야 할듯

 

3. 5월 식품들의 총매출 조회하기

-- 틀린 코드
SELECT A.PRODUCT_ID, A.PRODUCT_NAME, (A.PRICE * B.AMOUNT) TOTAL_SALES
FROM FOOD_PRODUCT A
JOIN (SELECT PRODUCT_ID, PRODUCE_DATE, SUM(AMOUNT) AMOUNT
     FROM FOOD_ORDER
     GROUP BY PRODUCT_ID) B
ON A.PRODUCT_ID = B.PRODUCT_ID
WHERE B.PRODUCE_DATE LIKE '2022-05%'
ORDER BY TOTAL_SALES DESC, A.PRODUCT_ID

-- 맞은 코드
SELECT A.PRODUCT_ID, A.PRODUCT_NAME, (A.PRICE * SUM(B.AMOUNT)) TOTAL_SALES
FROM FOOD_PRODUCT A
JOIN FOOD_ORDER B
ON A.PRODUCT_ID = B.PRODUCT_ID
WHERE B.PRODUCE_DATE LIKE '2022-05%'
GROUP BY B.PRODUCT_ID
ORDER BY TOTAL_SALES DESC, A.PRODUCT_ID

두 번째 코드가 왜 맞았는지는 알겠는데 첫 번째 코드가 왜 틀린 건지 모르겠다... 너무 꼬아서 생각한 걸까?

 

4. 없어진 기록 찾기

SELECT B.ANIMAL_ID, B.NAME
FROM ANIMAL_INS A
RIGHT JOIN ANIMAL_OUTS B
ON A.ANIMAL_ID = B.ANIMAL_ID
WHERE A.ANIMAL_ID IS NULL
ORDER BY ANIMAL_ID

ANIMAL_OUTS 기준으로 하기 때문에 RIGHT JOIN

또한 JOIN에서 ON 빼먹지 말것

 

5. 있었는데요 없었습니다

SELECT A.ANIMAL_ID, A.NAME
FROM ANIMAL_INS A
JOIN ANIMAL_OUTS B
ON A.ANIMAL_ID = B.ANIMAL_ID
WHERE A.DATETIME > B.DATETIME
ORDER BY A.DATETIME

6. 오랜 기간 보호한 동물(1)

SELECT A.NAME, A.DATETIME
FROM ANIMAL_INS A
LEFT JOIN ANIMAL_OUTS B
ON A.ANIMAL_ID = B.ANIMAL_ID
WHERE B.ANIMAL_ID IS NULL
ORDER BY A.DATETIME
LIMIT 3

ANIMAL_INS를 기준으로 ANIMAL_OUTS에서 NULL인 값을 찾아내려고 하는 것이기 때문에 LEFT JOIN을 해주며, LIMIT도 빼먹지 말자.

 

7. 보호소에서 중성화한 동물

SELECT A.ANIMAL_ID, A.ANIMAL_TYPE, A.NAME
FROM ANIMAL_INS A
JOIN ANIMAL_OUTS B
ON A.ANIMAL_ID = B.ANIMAL_ID
WHERE A.SEX_UPON_INTAKE != B.SEX_UPON_OUTCOME
ORDER BY A.ANIMAL_ID

8. 상품 별 오프라인 매출 구하기

SELECT A.PRODUCT_CODE, (A.PRICE * B.SALES_AMOUNT) SALES
FROM PRODUCT A
JOIN (SELECT PRODUCT_ID, SUM(SALES_AMOUNT) SALES_AMOUNT
      FROM OFFLINE_SALE
     GROUP BY PRODUCT_ID) B
ON A.PRODUCT_ID = B.PRODUCT_ID
ORDER BY SALES DESC, A.PRODUCT_CODE

JOIN문을 유의해서 작성해야 한다. GROUP BY가 JOIN문 뒤의 SELECT문 안에 들어간다.

JOIN문 이후의 SELECT문에서 PRODUCT_ID를 구해주는 이유는 ON A.PRODUCT_ID = B.PRODUCT_ID를 해주기 위함이다.

SUM의 위치도 유의해서 보자. 제품 id별 판매량이 총 몇개인지를 먼저 구한 후 가격을 곱해준다.

JOIN문 이후의 SELECT문에서 SUM(SALES_AMOUNT)까지만 적어주면 alias가 없어서 첫 번째 줄에서 오류가 난다. B.SALES_AMOUNT가 무엇인지 확실히 가리키기 위하여 alias를 적어줘야 한다.

 

 

마지막 문제는 5단계라 쫄아서 우선 생략. 나중에 풀 수 있으면 풀어봐야겠다.