[프로그래머스/MySQL] SQL 고득점 Kit 총정리 - JOIN

박찬병·2024년 11월 1일

Problem Solving

목록 보기
22/48

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

JOIN 문제들은 전체적으로 어려웠다.
나의 풀이가 비효율적일 수 있기 때문에 GPT에게 물어봐서 더 효율적으로 해결할 수 있을지 확인했다.


특정 기간동안 대여 가능한 자동차들의 대여비용 구하기

자동차의 정보를 담은 테이블, 자동차 대여 기록 정보를 담은 테이블, 그리고 자동차 종류 및 대여 기간 별 할인 정책 정보를 담은 테이블이 주어진다.
자동차 정보 테이블은 자동차 ID, 자동차 종류, 일일 대여 요금(원), 옵션 리스트로 구성된다.
대여 기록 정보 테이블은 기록 ID, 자동차 ID, 대여 시작일, 대여 종료일로 구성된다.
자동차 종류 및 대여 기간 별 할인 정책 정보 테이블은 정책 ID, 자동차 종류, 대여 기간 종류, 할인율(%)로 구성된다.

자동차 종류가 '세단' 또는 'SUV'인 자동차 중 2022-11-01부터 2022-11-30까지 대여 가능하고, 30일 간의 대여 금액이 50만원 이상 200만원 미만인 자동차의 ID, 종류, 대여 금액을 구하여라.
결과는 대여 금액의 내림차순, 자동차 종류의 오름차순, 자동차 ID의 내림차순으로 나타낸다.

나의 풀이

select CAR_ID, CAR_TYPE, FEE
from (select CAR_ID, CAR_TYPE, round(DAILY_FEE * 30 * (100-DISCOUNT_RATE)/100, 0) as FEE
      from CAR_RENTAL_COMPANY_CAR join CAR_RENTAL_COMPANY_DISCOUNT_PLAN using(CAR_TYPE)
      where (CAR_TYPE = '세단' or CAR_TYPE = 'SUV') and CAR_ID not in (
                select distinct CAR_ID
                from CAR_RENTAL_COMPANY_RENTAL_HISTORY
                where (START_DATE between '2022-11-01' and '2022-11-30') or
                      (END_DATE between '2022-11-01' and '2022-11-30') or
                      (START_DATE < '2022-11-01' and END_DATE > '2022-11-30'))
            and DURATION_TYPE = '30일 이상'
) A
where FEE >= 500000 and FEE < 2000000
order by FEE desc, CAR_TYPE asc, CAR_ID desc
  • 기본적인 아이디어는 대여 기록에서 주어진 기간에 대여할 수 있는 자동차를 확인하고, 각 자동차에 대해 대여 금액을 계산해서 금액 범위에 맞는 자동차를 최종적으로 얻는 것이다.
  • 쿼리의 가장 안쪽에서는 주어진 기간에 대여할 수 있는 자동차를 얻기 위해 대여 기간에 주어진 기간이 포함되는 자동차를 제외한다.
  • 그 다음에는 자동차 종류를 설정하여 세단 또는 SUV인 자동차만을 얻는다.
  • 가장 바깥쪽에서는 할인율을 이용해 대여 금액을 계산하고, 이를 조건으로 사용해 문제를 해결한다.
  • 실수할만한 점은 주어진 기간에 대여할 수 있는 자동차를 얻을 때, 대여 시작일이 주어진 기간 이전이면서 대여 종료일이 주어진 기간 이후인 경우를 누락할 수 있다는 점이다. 이를 유의해야 한다.

GPT-4o

SELECT DISTINCT
    C.CAR_ID, 
    C.CAR_TYPE, 
    ROUND(C.DAILY_FEE * 30 * (1 - COALESCE(D.DISCOUNT_RATE, 0) / 100), 0) AS FEE
FROM 
    CAR_RENTAL_COMPANY_CAR C
LEFT JOIN 
    CAR_RENTAL_COMPANY_RENTAL_HISTORY H ON C.CAR_ID = H.CAR_ID
LEFT JOIN 
    CAR_RENTAL_COMPANY_DISCOUNT_PLAN D ON C.CAR_TYPE = D.CAR_TYPE AND D.DURATION_TYPE = '30일 이상'
WHERE 
    (C.CAR_TYPE = '세단' OR C.CAR_TYPE = 'SUV')
    AND C.CAR_ID NOT IN (
        SELECT CAR_ID 
        FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY 
        WHERE (
            (START_DATE <= '2022-11-30' AND END_DATE >= '2022-11-01')
        )
    )
HAVING 
    FEE >= 500000 AND FEE < 2000000
ORDER BY 
    FEE DESC, 
    C.CAR_TYPE ASC, 
    C.CAR_ID DESC;
  • 대여 가능한 차를 찾고, 자동차의 종류를 맞추고, 마지막에 대여 금액을 계산하여 결과를 얻는다는 순서는 동일하다.
  • 대여 시작일과 대여 종료일에 대한 조건을 사용한 방식이 배울만하다. 더 직관적이다.
  • 사실 처음에는 가장 바깥쪽 쿼리에 SELECT DISTINCT가 아니라 SELECT로 설정되어 있어서 틀린 답이었다. 이 부분은 내가 수정하였다.
  • SELECT DISTINCT를 사용해야 하는 이유는 대여 기록 정보 테이블에서 CAR_ID가 여러 번 나타날 수 있기 때문이다. 사실 나의 풀이에서는 DISTINCT를 사용할 필요가 없는 반면, 여기서는 대여 기록 정보를 조인해서 사용하기 때문에 반드시 필요하다는 차이가 있다.

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

문제 설명

나의 풀이

select PRODUCT_ID, PRODUCT_NAME, sum(PRICE*AMOUNT) as TOTAL_SALES
from FOOD_PRODUCT join FOOD_ORDER using(PRODUCT_ID)
where year(PRODUCE_DATE) = 2022 and month(PRODUCE_DATE) = 5
group by PRODUCT_ID
order by TOTAL_SALES desc, PRODUCT_ID asc
  • 풀이 설명

GPT-4o

code
  • 풀이의 차이점 설명

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

문제 설명

나의 풀이

select FLAVOR
from FIRST_HALF as A join JULY as B using(FLAVOR)
group by FLAVOR
order by sum(A.TOTAL_ORDER + B.TOTAL_ORDER) desc
limit 3
  • 풀이 설명

GPT-4o

code
  • 풀이의 차이점 설명

조건에 맞는 도서와 저자 리스트 출력하기

문제 설명

나의 풀이

select BOOK_ID, AUTHOR_NAME, date_format(PUBLISHED_DATE, '%Y-%m-%d') as PUBLISHED_DATE
from BOOK join AUTHOR using(AUTHOR_ID)
where CATEGORY='경제'
order by PUBLISHED_DATE asc
  • 풀이 설명

GPT-4o

code
  • 풀이의 차이점 설명

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

문제 설명

나의 풀이

select MEMBER_NAME, REVIEW_TEXT, date_format(REVIEW_DATE, '%Y-%m-%d') as REVIEW_DATE
from MEMBER_PROFILE join REST_REVIEW using(MEMBER_ID)
where MEMBER_NAME in (select MEMBER_NAME
                      from MEMBER_PROFILE join REST_REVIEW using(MEMBER_ID)
                      group by MEMBER_NAME
                      having count(*) >= all (select count(*)
                                              from REST_REVIEW
                                              group by MEMBER_ID))
order by REVIEW_DATE asc, REVIEW_TEXT asc
  • 풀이 설명

GPT-4o

code
  • 풀이의 차이점 설명

없어진 기록 찾기

문제 설명

나의 풀이

select ANIMAL_ID, NAME
from ANIMAL_OUTS
where ANIMAL_ID not in (select ANIMAL_ID
                        from ANIMAL_INS)
order by ANIMAL_ID
  • 풀이 설명

GPT-4o

code
  • 풀이의 차이점 설명

있었는데요 없었습니다

문제 설명

나의 풀이

select ANIMAL_ID, INS.NAME NAME
from ANIMAL_INS INS join ANIMAL_OUTS OUTS using(ANIMAL_ID)
where INS.DATETIME > OUTS.DATETIME
order by INS.DATETIME asc
  • 풀이 설명

GPT-4o

code
  • 풀이의 차이점 설명

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

문제 설명

나의 풀이

select NAME, DATETIME
from ANIMAL_INS
where ANIMAL_ID not in (select ANIMAL_ID
                        from ANIMAL_OUTS)
order by DATETIME
limit 3
  • 풀이 설명

GPT-4o

code
  • 풀이의 차이점 설명

보호소에서 중성화한 동물

문제 설명

나의 풀이

select ANIMAL_ID, ANIMAL_TYPE, NAME
from ANIMAL_INS
where SEX_UPON_INTAKE like "Intact%"
      and ANIMAL_ID in (select ANIMAL_ID
                        from ANIMAL_OUTS
                        where SEX_UPON_OUTCOME like "Neutered%"
                              or SEX_UPON_OUTCOME like "Spayed%")
order by ANIMAL_ID
  • 풀이 설명

GPT-4o

code
  • 풀이의 차이점 설명

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

문제 설명

나의 풀이

select PRODUCT_CODE, PRICE * AMOUNT as SALES
from PRODUCT A join (select PRODUCT_ID, sum(SALES_AMOUNT) as AMOUNT
                     from OFFLINE_SALE
                     group by PRODUCT_ID) B
    using(PRODUCT_ID)
order by SALES desc, PRODUCT_CODE asc
  • 풀이 설명

GPT-4o

code
  • 풀이의 차이점 설명

상품을 구매한 회원 비율 구하기

문제 설명

나의 풀이

select year(A.SALES_DATE) as YEAR, month(A.SALES_DATE) as MONTH, count(distinct USER_ID) as PURCHASED_USERS, round(count(distinct USER_ID)/B.TOTAL_USER, 1) as PURCHASED_RATIO
from ONLINE_SALE as A join (select USER_ID, (select count(USER_ID)
                                             from USER_INFO
                                             where JOINED like '2021%') as TOTAL_USER
                            from USER_INFO
                            where JOINED like '2021%') as B using(USER_ID)
group by YEAR, MONTH
order by YEAR asc, MONTH asc
  • 풀이 설명

GPT-4o

code
  • 풀이의 차이점 설명

FrontEnd 개발자 찾기

문제 설명

나의 풀이

select distinct A.ID, A.EMAIL, A.FIRST_NAME, A.LAST_NAME
from DEVELOPERS A join (select ID, CODE
                        from SKILLCODES C join (select ID, 'Front End' as CATEGORY
                                                from DEVELOPERS) D using(CATEGORY)) as B using(ID)
where A.SKILL_CODE & B.CODE > 0
order by ID asc
  • 풀이 설명

GPT-4o

code
  • 풀이의 차이점 설명

0개의 댓글