문제 풀이 링크: https://datalemur.com/questions/pizzas-topping-cost
McKinsey SQL Interview Question | DataLemur
McKinsey SQL Interview Question: Write a query to calculate the cost of 3-topping pizzas.
datalemur.com
🍕 3-토핑 피자 조합 비용 계산 문제 요약
목적: 서로 다른 3개 토핑으로 만들 수 있는 모든 피자 조합에 대해 총 재료 비용을 계산하고 출력
조건:
- 토핑은 반복 없이 서로 달라야 함 (예: 'Pepperoni,Pepperoni,Onion' ❌)
- 토핑 이름은 알파벳 순서대로 나열해야 함 (예: 'Chicken,Onions,Sausage' ✅)
- 출력 정렬 기준:
- 총 비용(total_cost) 내림차순
- 비용이 같으면 토핑 이름 오름차순 정렬
- 토핑 이름 사이는 띄어쓰기 없이 쉼표(,) 로 연결
1. 내 풀이
- CROSS JOIN 으로 모든 조합 생성
- (모든 p1 × p2 × p3 조합 → 경우의 수 엄청 많아짐)
- 이후 WHERE 조건으로
- p1.topping_name < p2.topping_name
- p2.topping_name < p3.topping_name
- → 중복 조합과 순서 무시를 걸러냄
- 쿼리 구조는 간단하지만, JOIN이 비효율적 (모든 조합을 만들고 거르는 방식)
- 데이터가 많으면 느려질 수 있음
SELECT CONCAT(p1.topping_name,',', p2.topping_name, ',', p3.topping_name) AS pizza,
p1.ingredient_cost + p2.ingredient_cost + p3.ingredient_cost AS total_cost
FROM pizza_toppings p1
CROSS JOIN
pizza_toppings p2,
pizza_toppings p3
WHERE p1.topping_name < p2.topping_name
AND p2.topping_name < p3.topping_name
ORDER BY total_cost DESC, pizza;
2. 3개 조합에서 유용한 풀이
- INNER JOIN 두 번을 통해 조합 생성
- 조합 조건:
- p1.topping_name < p2.topping_name
- p2.topping_name < p3.topping_name
- → 이 조건을 통해 중복 없이 알파벳 순서로 3개 토핑 조합 생성
- 가장 빠르고 가독성 좋은 풀이
- 단, 3개 고정 → 4개 이상 조합을 만들 때는 수정 필요
SELECT
CONCAT(p1.topping_name, ',', p2.topping_name, ',', p3.topping_name) AS pizza,
p1.ingredient_cost + p2.ingredient_cost + p3.ingredient_cost AS total_cost
FROM pizza_toppings AS p1
INNER JOIN pizza_toppings AS p2
ON p1.topping_name < p2.topping_name
INNER JOIN pizza_toppings AS p3
ON p2.topping_name < p3.topping_name
ORDER BY total_cost DESC, pizza;
3. 조합 개수가 늘어나도 사용성이 좋은 쿼리
- 1개 토핑부터 시작해서 점점 토핑을 추가하는 RECURSIVE CTE 사용
- topping_numbers를 세어가면서1개 → 2개 → 3개로 조합 확장
- 토핑 추가할 때 기존 조합(anchor)의 topping_name < 추가할 토핑(addon)의 topping_name 조건을 걸어 중복과 순서 문제 해결
- 3개 조합이 완성된 경우만 (topping_numbers = 3) 필터링
- STRING_TO_ARRAY로 topping_name을 배열로 만들고, UNNEST로 토핑을 하나씩 꺼냄
- UNNEST: 배열을 한 줄씩(row)으로 펼쳐주는 함수
- STRING_TO_ARRAY: 문자열을 구분자(,)를 기준으로 배열로 쪼개는 함수
- 다시 STRING_AGG로 알파벳 순서대로 토핑 이름을 합침
- STRING_AGG: 여러 줄(row)의 값을 하나의 문자열로 합치는 함수
WITH RECURSIVE all_toppings AS ( -- 1단계: 재귀적으로 조합 만들기
-- 시작: 토핑 1개
SELECT
topping_name::VARCHAR,
ingredient_cost::DECIMAL AS total_cost,
1 AS topping_numbers
FROM pizza_toppings
UNION ALL
-- 확장: 하나 더 추가
SELECT
CONCAT(addon.topping_name, ',', anchor.topping_name) AS topping_name,
addon.ingredient_cost + anchor.total_cost AS total_cost,
topping_numbers + 1
FROM
pizza_toppings AS addon,
all_toppings AS anchor
WHERE anchor.topping_name < addon.topping_name
),
arrange AS ( -- 2단계: 토핑 정렬하기
SELECT
topping_name,
UNNEST(STRING_TO_ARRAY(topping_name, ',')) AS single_topping,
total_cost
FROM all_toppings
WHERE topping_numbers = 3
)
-- 3단계: 정렬된 토핑을 다시 합치고 최종 출력
SELECT
STRING_AGG(single_topping, ',' ORDER BY single_topping) AS pizza,
total_cost
FROM arrange
GROUP BY topping_name, total_cost
ORDER BY total_cost DESC, pizza;
'SQL' 카테고리의 다른 글
Card Launch Success: JPMorgan SQL Interview Question (0) | 2025.05.03 |
---|---|
Department vs. Company Salary: FAANG SQL Interview Question (0) | 2025.04.30 |
Histogram of Users and Purchases: Walmart SQL Interview Question (0) | 2025.04.28 |
User Shopping Sprees: Amazon SQL Interview Question (0) | 2025.04.28 |
Advertiser Status: Facebook SQL Interview Question (0) | 2025.04.26 |