프로그래머스 SQL 고득점 Kit - JOIN 문제 풀이 모음 (MySQL)

정진희·2025년 4월 19일

SQL 문제 풀이

목록 보기
3/6
post-thumbnail

모든 문제 풀이 완료 😄

[Lv.2] - 조건에 맞는 도서와 저자 리스트 출력하기

SELECT BOOK_ID, AUTHOR_NAME, DATE_FORMAT(PUBLISHED_DATE, '%Y-%m-%d')
FROM BOOK JOIN AUTHOR USING(AUTHOR_ID)
WHERE CATEGORY = '경제'
ORDER BY 3;

[Lv.2] - 상품 별 오프라인 매출 구하기

SELECT PRODUCT_CODE, SUM(P.PRICE * SALES_AMOUNT) SALES
FROM PRODUCT P JOIN OFFLINE_SALE S ON P.PRODUCT_ID = S.PRODUCT_ID
GROUP BY PRODUCT_CODE
ORDER BY 2 DESC, PRODUCT_CODE;

[Lv.3] - 오랜 기간 보호한 동물(1)

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

[Lv.3] - 있었는데요 없었습니다

SELECT I.ANIMAL_ID, I.NAME
FROM ANIMAL_INS I JOIN ANIMAL_OUTS O USING (ANIMAL_ID)
WHERE I.DATETIME > O.DATETIME
ORDER BY I.DATETIME;

[Lv.3] - 없어진 기록 찾기

  • RIGHT JOIN : 오른쪽 테이블의 데이터를 기준으로 나와서 왼쪽 테이블에 데이터가 없는 것은 데이터가 나오지 않는다.
SELECT O.ANIMAL_ID, O.NAME
FROM ANIMAL_INS I RIGHT JOIN ANIMAL_OUTS O USING(ANIMAL_ID)
WHERE I.ANIMAL_ID IS NULL;

[Lv.4] - 보호소에서 중성화한 동물

SELECT O.ANIMAL_ID, O.ANIMAL_TYPE, O.NAME
FROM ANIMAL_INS I JOIN ANIMAL_OUTS O USING(ANIMAL_ID)
WHERE I.SEX_UPON_INTAKE LIKE 'Intact %' AND 
     (O.SEX_UPON_OUTCOME LIKE 'Spayed %' OR O.SEX_UPON_OUTCOME LIKE 'Neutered %');

[Lv.4] - 5월 식품들의 총매출 조회하기

SELECT P.PRODUCT_ID, P.PRODUCT_NAME, PRICE*SUM(O.AMOUNT) AS TOTAL_SALES
FROM FOOD_PRODUCT P JOIN FOOD_ORDER O ON P.PRODUCT_ID = O.PRODUCT_ID
WHERE PRODUCE_DATE LIKE '2022-05%'
GROUP BY 1
ORDER BY TOTAL_SALES DESC, 1 ASC;

[Lv.4] - 주문량이 많은 아이스크림들 조회하기

SELECT F.FLAVOR
FROM FIRST_HALF F INNER JOIN 
     (SELECT FLAVOR, SUM(TOTAL_ORDER) AS JULY_TOTAL_ORDER
      FROM JULY GROUP BY FLAVOR) J ON F.FLAVOR = J.FLAVOR
ORDER BY F.TOTAL_ORDER + JULY_TOTAL_ORDER DESC
LIMIT 3;

[Lv.4] - 그룹별 조건에 맞는 식당 목록 출력하기

SELECT MEMBER_NAME, REVIEW_TEXT, DATE_FORMAT(REVIEW_DATE, "%Y-%m-%d") AS REVIEW_DATE
FROM MEMBER_PROFILE P JOIN REST_REVIEW R ON P.MEMBER_ID = R.MEMBER_ID
WHERE P.MEMBER_ID = (SELECT MEMBER_ID
                     FROM REST_REVIEW 
                     GROUP BY MEMBER_ID
                     ORDER BY COUNT(*) DESC
                     LIMIT 1)
ORDER BY REVIEW_DATE, REVIEW_TEXT;

[Lv.4] - FrontEnd 개발자 찾기

-- ID 당 여러 개의 보유 스킬이 붙어 여러 ID가 뜨기 때문에 DISTINCT를 꼭 써줘야 한다.
SELECT DISTINCT D.ID, D.EMAIL, D.FIRST_NAME, D.LAST_NAME
-- & : 비트 연산
FROM SKILLCODES S JOIN DEVELOPERS D ON S.CODE = S.CODE & D.SKILL_CODE
WHERE S.CATEGORY = 'Front End'
ORDER BY D.ID;

[Lv.4] - 특정 기간동안 대여 가능한 자동차들의 대여비용 구하기

참고한 블로그

SELECT C.CAR_ID, C.CAR_TYPE, ROUND(C.DAILY_FEE * 30 * (1 - (DISCOUNT_RATE / 100))) AS FEE
FROM (SELECT * FROM CAR_RENTAL_COMPANY_CAR 
      WHERE CAR_TYPE IN ('세단', 'SUV')) C -- 자동차 종류가 세단과 SUV인 것만
        JOIN CAR_RENTAL_COMPANY_RENTAL_HISTORY H ON C.CAR_ID = H.CAR_ID -- CAR_ID기준으로
        JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN P ON C.CAR_TYPE = P.CAR_TYPE -- CAR_TYPE기준으로
WHERE C.CAR_ID NOT IN ( 
        SELECT CAR_ID
        FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
        WHERE END_DATE >= '2022-11-01' AND START_DATE <= '2022-12-01'        
) AND P.DURATION_TYPE like '30%' -- 그리고 대여 기간이 30일 이상인 것을 검색해야하므로
GROUP BY C.CAR_ID -- 자동차 ID 기준으로 그룹화하여
-- select 절에 있는 집계함수 컬럼을 사용하기 위해 having 절에 작성함
HAVING FEE BETWEEN 500000 AND 2000000 -- 30일간의 대여 금액이 50만원 200만원 미만인 자동차 
ORDER BY FEE DESC, CAR_TYPE, CAR_ID DESC;

[Lv.5] - 상품을 구매한 회원 비율 구하기

  • 풀이 1

    SELECT YEAR(S.SALES_DATE) AS YEAR, MONTH(S.SALES_DATE) AS MONTH, COUNT(DISTINCT S.USER_ID) AS PURCHASED_USERS,
           ROUND(COUNT(DISTINCT S.USER_ID) / (SELECT COUNT(USER_ID) FROM USER_INFO WHERE JOINED LIKE '2021%'), 1) AS PUCHASED_RATIO
    FROM USER_INFO I JOIN ONLINE_SALE S ON I.USER_ID = S.USER_ID
    WHERE I.JOINED LIKE '2021%'
    GROUP BY MONTH(S.SALES_DATE)
    ORDER BY 1, 2;
  • 풀이 2 : 개선된 풀이

    SELECT YEAR(S.SALES_DATE) AS YEAR, MONTH(S.SALES_DATE) AS MONTH, COUNT(DISTINCT S.USER_ID) AS PURCHASED_USERS,
    -- 1.0 곱하는 이유 : 정수 나눗셈 방지, 자동 실수 변환으로 정확한 비율 계산
        ROUND(COUNT(DISTINCT S.USER_ID) * 1.0 / 
             (SELECT COUNT(*) FROM USER_INFO WHERE JOINED BETWEEN '2021-01-01' AND '2021-12-31'), 1) AS PURCHASED_RATIO
    FROM USER_INFO I
    JOIN ONLINE_SALE S ON I.USER_ID = S.USER_ID
    -- LIKE보다 범위 조건이 명확하고 빠름
    WHERE I.JOINED BETWEEN '2021-01-01' AND '2021-12-31'
    -- 좀 더 정확하고 명확한 그룹핑
    GROUP BY YEAR(S.SALES_DATE), MONTH(S.SALES_DATE)
    ORDER BY YEAR, MONTH;
profile
고민하고, 공부해서 발전하는 개발자가 되자🔥

0개의 댓글