[TIL]_2025.04.11 본캠프 54일차 (1) : QCC 4회차

JIYUU·2025년 4월 11일

오늘은 드디어 만점! 몇 일간 코드카타를 열심히 한 보람이 있었다. 아니면 문제 난이도가 내려간 걸 수도 있겠다.

문제 1번.

지역별로 매출이 가장 높은 매장을 조회하는 SQL문을 작성해주세요.
단, 해당 지역에 매장이 두 개 이상인 경우만 결과에 포함해주세요.
결과는 지역 이름을 기준으로 오름차순 정렬해주세요.

  • 제출한 답
-- 지역별 가장 매출 높은 매장 조회
-- 지역에 매장 두개 이상
-- 지역 이름 기준 asc

select region_name, sales as highest_sales
from stores
where (region_name, sales) in (
  select region_name, max(sales)
  from stores
  where region_name in (
  select region_name
  from stores
  group by region_name
  having count(*) >= 2
  )
  group by region_name
)
order by region_name asc
  • 정답
select region_name, max(sales) as highest_sales
from stores
group by region_name
having count(region_name) >= 2
order by region_name asc
  • 회고
    진짜 진짜 또 어렵게 접근한 문제.. 일단 긴장하면 문제를 어렵게 보게 되는 것 같다.
    사실 그냥 group by, having으로 푸는 문제였다.

문제 2번.

제품 X와 Y가 같은 주문에 포함된 경우를 계산합니다.
두 제품은 서로 다른 이름이어야 하며 한 쌍의 경우는 다른 순서로도 포함됩니다. (쌍 중복 가능)
결과는 각 제품 쌍과 해당 제품이 함께 포함된 주문 수를 반환해야 합니다.
제품 이름 X, Y를 기준으로 알파벳 순으로 오름차순 정렬합니다.

  • 제출한 답
-- X, Y가 같은 주문에 포함된 경우
-- 서로 다른 이름, 순서 달라도 포함
-- 각 제품 쌍, 제품 포함된 주문 수
-- 제품 이름 기준 asc
select 
  p1.name as name_x,
  p2.name as name_y,
  count(distinct p1.cart_id) as orders
from cart_products p1
join cart_products p2
on p1.cart_id = p2.cart_id -- 같은 주문에 포함된 경우
and p1.name != p2.name -- 서로 다른 이름이어야 함
group by p1.name, p2.name
order by name_x, name_y
  • 정답
select 
	a.name as name_X, 
	b.name as name_y, 
    count(distinct a.cart_id) orders
from cart_products a
join cart_products b
on a.cart_id = b.cart_id
and a.name != b.name
group by 1, 2
order by 1, 2
  • 회고
    오랜만에 정답과 동일하게 푼 문제였다. and 조건에 !=아니라 <나 >를 넣으면 쌍 중복을 제거할 수 있다.

문제 3번.

최근 특정 사용자들이 결제를 하지 않고 상품을 주문하거나, 결제를 하지 않은 시점에 이미 상품을 주문하는 버그가 발견되었습니다. 해당 버그를 악용한 사용자를 파악하기 위해 SQL 문을 작성해주세요.
다음 조건에 해당되는 사용자 수를 출력해주세요.
결제를 하지 않고 상품을 주문한 사용자
첫 번째 결제일보다 이전에 상품을 주문한 사용자

  • 제출한 답
-- 결제없이 주문된 사용자 수 출력
-- 첫번째 결제일 > 주문 일자인 사용자 수
select count(distinct o.user_id) as cnt
from orders o
left join (
  select user_id, amount, pay_date, min(pay_date) as first_payment
  from payments
  group by user_id) p
on o.user_id = p.user_id
where (p.first_payment is null) or (o.order_date < p.first_payment)
  • 정답
with first_payment as (
	select user_id, min(pay_date) first_payment_date
	group by 1
)
select o.*, fp.fisrt_payment_date
from orders o
left join first_payment fp
on o.user_id = fp.user_id
where fp.user_id is null and or fp.user_id is null
  • 회고
    정답은 with를 사용해서 문제를 풀었다. with를 사용한다면 본쿼리가 좀 더 간결해지는 것 같다.

0개의 댓글