콘텐츠로 이동

종합 문제

사용 테이블

products — 상품 (이름, 가격, 재고, 브랜드)

customers — 고객 (등급, 포인트, 가입채널)

orders — 주문 (상태, 금액, 일시)

reviews — 리뷰 (평점, 내용)

payments — 결제 (방법, 금액, 상태)

categories — 카테고리 (부모-자식 계층)

suppliers — 공급업체 (업체명, 연락처)

학습 범위

SELECT, WHERE, ORDER BY, LIMIT, Aggregate functions, GROUP BY, HAVING, IS NULL, COALESCE, CASE

1. 판매 중인 상품(is_active = 1) 중 가격이 가장 비싼 상위 5개의 이름, 브랜드, 가격을 조회

판매 중인 상품(is_active = 1) 중 가격이 가장 비싼 상위 5개의 이름, 브랜드, 가격을 조회하세요.

힌트 1: WHERE로 필터링 + ORDER BY DESC + LIMIT 조합입니다.

정답
SELECT name, brand, price
FROM products
WHERE is_active = 1
ORDER BY price DESC
LIMIT 5;

실행 결과 (5행)

name brand price
MacBook Air 15 M3 실버 Apple 5,481,100.00
ASUS Dual RTX 5070 Ti [특별 한정판 에디션] 저소... ASUS 4,496,700.00
Razer Blade 18 블랙 Razer 4,353,100.00
Razer Blade 16 실버 Razer 3,702,900.00
ASUS ROG Strix G16CH 화이트 ASUS 3,671,500.00

2. VIP 등급 고객 중 마지막 로그인 기록이 있는 고객의 이름과 마지막 로그인일을 최근순으로 10건 조회하세요

VIP 등급 고객 중 마지막 로그인 기록이 있는 고객의 이름과 마지막 로그인일을 최근순으로 10건 조회하세요.

힌트 1: WHERE grade = 'VIP' AND last_login_at IS NOT NULL로 두 조건을 결합합니다.

정답
SELECT name, last_login_at
FROM customers
WHERE grade = 'VIP'
  AND last_login_at IS NOT NULL
ORDER BY last_login_at DESC
LIMIT 10;

실행 결과 (총 10행 중 상위 7행)

name last_login_at
김영희 2025-12-30 20:20:12
박은서 2025-12-30 17:25:30
윤준영 2025-12-30 17:24:28
노수빈 2025-12-30 12:28:17
성은주 2025-12-30 02:06:50
김시우 2025-12-30 00:15:41
성진우 2025-12-29 21:08:21

3. 2024년 취소된 주문의 주문번호, 주문 금액, 취소일을 최근 취소 순으로 10건 조회하세요.

2024년 취소된 주문의 주문번호, 주문 금액, 취소일을 최근 취소 순으로 10건 조회하세요.

힌트 1: WHERE ordered_at LIKE '2024%' AND cancelled_at IS NOT NULL로 조건을 결합합니다.

정답
SELECT order_number, total_amount, cancelled_at
FROM orders
WHERE ordered_at LIKE '2024%'
  AND cancelled_at IS NOT NULL
ORDER BY cancelled_at DESC
LIMIT 10;

실행 결과 (총 10행 중 상위 7행)

order_number total_amount cancelled_at
ORD-20241231-31231 1,905,400.00 2025-01-01 23:25:27
ORD-20241229-31194 657,900.00 2024-12-31 11:37:44
ORD-20241228-31179 68,900.00 2024-12-30 00:01:41
ORD-20241228-31177 289,100.00 2024-12-28 21:35:05
ORD-20241226-31148 69,400.00 2024-12-27 20:44:43
ORD-20241225-31134 2,841,800.00 2024-12-26 18:43:50
ORD-20241223-31096 234,768.00 2024-12-25 19:56:46

4. 평점 4점 이상인 리뷰 수와 평균 평점을 구하세요. 평균은 소수점 2자리까지 표시합니다.

평점 4점 이상인 리뷰 수와 평균 평점을 구하세요. 평균은 소수점 2자리까지 표시합니다.

힌트 1: WHERE rating >= 4로 필터링 후 COUNT(*)ROUND(AVG(rating), 2)를 사용합니다.

정답
SELECT COUNT(*) AS high_rating_count,
       ROUND(AVG(rating), 2) AS avg_rating
FROM reviews
WHERE rating >= 4;

실행 결과 (1행)

high_rating_count avg_rating
6008 4.57

5. 브랜드별 판매 중인 상품 수를 구하되, 10개 이상인 브랜드만 상품 수 내림차순으로 조회하세요.

브랜드별 판매 중인 상품 수를 구하되, 10개 이상인 브랜드만 상품 수 내림차순으로 조회하세요.

힌트 1: WHERE is_active = 1 + GROUP BY brand + HAVING COUNT(*) >= 10 조합입니다.

정답
SELECT brand, COUNT(*) AS product_count
FROM products
WHERE is_active = 1
GROUP BY brand
HAVING COUNT(*) >= 10
ORDER BY product_count DESC;

실행 결과 (6행)

brand product_count
삼성전자 21
ASUS 21
MSI 12
로지텍 11
TP-Link 11
LG전자 11

6. 고객 등급별 평균 적립금을 구하되, 등급을 한글로 표시하세요. 평균 적립금이 높은 순으로 정렬합니다.

고객 등급별 평균 적립금을 구하되, 등급을 한글로 표시하세요. 평균 적립금이 높은 순으로 정렬합니다.

힌트 1: CASE로 등급 변환 + GROUP BY + AVG + ORDER BY 조합입니다.

정답
SELECT CASE grade
           WHEN 'VIP' THEN 'VIP'
           WHEN 'GOLD' THEN '골드'
           WHEN 'SILVER' THEN '실버'
           WHEN 'BRONZE' THEN '브론즈'
       END AS grade_kr,
       ROUND(AVG(point_balance)) AS avg_points
FROM customers
GROUP BY grade
ORDER BY avg_points DESC;

실행 결과 (4행)

grade_kr avg_points
VIP 407,015.00
골드 147,711.00
실버 95,042.00
브론즈 16,779.00

7. 결제 수단별 총 결제 금액과 건수를 구하되, 총 금액이 10억 이상인 수단만 조회하세요.

결제 수단별 총 결제 금액과 건수를 구하되, 총 금액이 10억 이상인 수단만 조회하세요.

힌트 1: GROUP BY method + HAVING SUM(amount) >= 1000000000 조합입니다.

정답
SELECT method,
       COUNT(*) AS payment_count,
       ROUND(SUM(amount)) AS total_amount
FROM payments
GROUP BY method
HAVING SUM(amount) >= 1000000000
ORDER BY total_amount DESC;

실행 결과 (6행)

method payment_count total_amount
card 16,841 17,004,951,634.00
kakao_pay 7486 7,563,829,668.00
naver_pay 5715 5,998,835,720.00
bank_transfer 3718 3,753,149,013.00
point 1921 1,951,369,604.00
virtual_account 1876 1,911,359,424.00

8. 가입 경로가 NULL인 고객의 등급별 수를 구하세요. CASE로 등급 순서를 지정하여 VIP부터 표시합니다.

가입 경로가 NULL인 고객의 등급별 수를 구하세요. CASE로 등급 순서를 지정하여 VIP부터 표시합니다.

힌트 1: WHERE acquisition_channel IS NULL + GROUP BY grade + ORDER BY CASE 조합입니다.

정답
SELECT grade, COUNT(*) AS customer_count
FROM customers
WHERE acquisition_channel IS NULL
GROUP BY grade
ORDER BY CASE grade
             WHEN 'VIP' THEN 1
             WHEN 'GOLD' THEN 2
             WHEN 'SILVER' THEN 3
             WHEN 'BRONZE' THEN 4
         END;

9. 주문 상태별 건수와 평균 주문 금액을 구하되, 배송 요청사항의 입력률(%)도 함께 표시하세요. 건수가 많은

주문 상태별 건수와 평균 주문 금액을 구하되, 배송 요청사항의 입력률(%)도 함께 표시하세요. 건수가 많은 순으로 정렬합니다.

힌트 1: COUNT(notes) * 100.0 / COUNT(*)로 입력률을 계산합니다. NULL과 집계 함수의 관계를 활용합니다.

정답
SELECT status,
       COUNT(*) AS order_count,
       ROUND(AVG(total_amount)) AS avg_amount,
       ROUND(COUNT(notes) * 100.0 / COUNT(*), 1) AS notes_rate_pct
FROM orders
GROUP BY status
ORDER BY order_count DESC;

실행 결과 (총 9행 중 상위 7행)

status order_count avg_amount notes_rate_pct
confirmed 34,393 999,814.00 35.30
cancelled 1859 1,045,258.00 34.30
return_requested 507 1,600,567.00 33.10
returned 493 1,337,616.00 34.90
delivered 125 1,566,146.00 28.80
pending 82 1,063,783.00 37.80
shipped 51 1,452,364.00 31.40

10. 상품을 재고 상태(품절/부족/보통/충분)로 분류하고, 각 그룹의 상품 수와 평균 가격을 구하세요. 판매 중인

상품을 재고 상태(품절/부족/보통/충분)로 분류하고, 각 그룹의 상품 수와 평균 가격을 구하세요. 판매 중인 상품만 대상입니다.

힌트 1: WHERE is_active = 1 + CASE로 재고 분류 + GROUP BY + 집계 함수 조합입니다.

정답
SELECT CASE
           WHEN stock_qty = 0 THEN '품절'
           WHEN stock_qty <= 10 THEN '부족'
           WHEN stock_qty <= 100 THEN '보통'
           ELSE '충분'
       END AS stock_status,
       COUNT(*) AS product_count,
       ROUND(AVG(price)) AS avg_price
FROM products
WHERE is_active = 1
GROUP BY stock_status
ORDER BY product_count DESC;

실행 결과 (4행)

stock_status product_count avg_price
충분 181 669,318.00
보통 34 662,359.00
부족 2 50,900.00
품절 1 23,000.00

11. 브랜드별 판매 중인 상품 수, 평균 가격, 평균 마진율(%)을 구하세요. 상품 수가 5개 이상인 브랜드만 평

브랜드별 판매 중인 상품 수, 평균 가격, 평균 마진율(%)을 구하세요. 상품 수가 5개 이상인 브랜드만 평균 마진율이 높은 순으로 조회합니다.

힌트 1: 마진율 = (price - cost_price) * 100.0 / price. WHERE + GROUP BY + HAVING + ORDER BY 조합입니다.

정답
SELECT brand,
       COUNT(*) AS product_count,
       ROUND(AVG(price)) AS avg_price,
       ROUND(AVG((price - cost_price) * 100.0 / price), 1) AS avg_margin_pct
FROM products
WHERE is_active = 1
GROUP BY brand
HAVING COUNT(*) >= 5
ORDER BY avg_margin_pct DESC;

실행 결과 (총 17행 중 상위 7행)

brand product_count avg_price avg_margin_pct
Microsoft 5 129,260.00 38.20
SteelSeries 7 212,643.00 31.60
TP-Link 11 128,764.00 30.30
NZXT 5 213,100.00 29.70
로지텍 11 115,127.00 28.00
ASUS 21 1,589,552.00 28.00
ASRock 9 493,244.00 25.60

12. 연도별 주문 건수, 총 매출, 평균 주문 금액, 취소 건수를 구하세요. 취소 건수는 cancelled_at이

연도별 주문 건수, 총 매출, 평균 주문 금액, 취소 건수를 구하세요. 취소 건수는 cancelled_at이 NULL이 아닌 행의 수입니다.

힌트 1: SUBSTR(ordered_at, 1, 4)로 연도 추출. COUNT(cancelled_at)은 NULL이 아닌 행만 셉니다.

정답
SELECT SUBSTR(ordered_at, 1, 4) AS year,
       COUNT(*) AS order_count,
       ROUND(SUM(total_amount)) AS total_revenue,
       ROUND(AVG(total_amount)) AS avg_amount,
       COUNT(cancelled_at) AS cancelled_count
FROM orders
GROUP BY year
ORDER BY year;

실행 결과 (총 10행 중 상위 7행)

year order_count total_revenue avg_amount cancelled_count
2016 416 331,746,909.00 797,469.00 15
2017 709 653,085,068.00 921,135.00 41
2018 1319 1,249,197,907.00 947,080.00 64
2019 2589 2,620,111,601.00 1,012,017.00 116
2020 4319 4,468,755,264.00 1,034,674.00 191
2021 5841 6,044,718,738.00 1,034,877.00 270
2022 5203 5,302,071,035.00 1,019,041.00 256

13. 가입 경로별 고객 수, VIP 비율(%), 평균 적립금을 구하세요. 경로가 NULL이면 '미분류'로 표시하고

가입 경로별 고객 수, VIP 비율(%), 평균 적립금을 구하세요. 경로가 NULL이면 '미분류'로 표시하고, 고객 수가 많은 순으로 정렬합니다.

힌트 1: COALESCE로 NULL 대체 + SUM(CASE WHEN grade = 'VIP' THEN 1 ELSE 0 END)로 VIP 수 집계 + GROUP BY 조합입니다.

정답
SELECT COALESCE(acquisition_channel, '미분류') AS channel,
       COUNT(*) AS customer_count,
       ROUND(SUM(CASE WHEN grade = 'VIP' THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) AS vip_rate_pct,
       ROUND(AVG(point_balance)) AS avg_points
FROM customers
GROUP BY COALESCE(acquisition_channel, '미분류')
ORDER BY customer_count DESC;

실행 결과 (5행)

channel customer_count vip_rate_pct avg_points
search_ad 1543 7.50 62,449.00
social 1425 6.20 54,311.00
organic 1146 7.10 76,371.00
referral 708 7.20 66,944.00
direct 408 7.80 70,562.00

14. 2024년 월별 주문 건수와 평균 주문 금액을 구하되, 계절(봄/여름/가을/겨울)도 함께 표시하세요.

2024년 월별 주문 건수와 평균 주문 금액을 구하되, 계절(봄/여름/가을/겨울)도 함께 표시하세요.

힌트 1: SUBSTR로 월 추출 + CASE로 계절 분류 + GROUP BY + 집계 조합입니다.

정답
SELECT SUBSTR(ordered_at, 1, 7) AS month,
       CASE
           WHEN CAST(SUBSTR(ordered_at, 6, 2) AS INTEGER) IN (3, 4, 5) THEN '봄'
           WHEN CAST(SUBSTR(ordered_at, 6, 2) AS INTEGER) IN (6, 7, 8) THEN '여름'
           WHEN CAST(SUBSTR(ordered_at, 6, 2) AS INTEGER) IN (9, 10, 11) THEN '가을'
           ELSE '겨울'
       END AS season,
       COUNT(*) AS order_count,
       ROUND(AVG(total_amount)) AS avg_amount
FROM orders
WHERE ordered_at LIKE '2024%'
GROUP BY month
ORDER BY month;

실행 결과 (총 12행 중 상위 7행)

month season order_count avg_amount
2024-01 겨울 346 925,700.00
2024-02 겨울 465 966,554.00
2024-03 601 948,084.00
2024-04 506 980,283.00
2024-05 415 1,140,347.00
2024-06 여름 415 962,619.00
2024-07 여름 414 926,084.00

15. 리뷰를 평점별로 집계하되, 각 평점의 한글 라벨, 건수, 전체 대비 비율(%), 제목 입력률(%)을 함께 표

리뷰를 평점별로 집계하되, 각 평점의 한글 라벨, 건수, 전체 대비 비율(%), 제목 입력률(%)을 함께 표시하세요. 평점 높은 순으로 정렬합니다.

힌트 1: CASE로 평점 라벨 + COUNT(*) + 비율 계산 + COUNT(title) 조합입니다.

정답
SELECT rating,
       CASE rating
           WHEN 5 THEN '최고'
           WHEN 4 THEN '좋음'
           WHEN 3 THEN '보통'
           WHEN 2 THEN '별로'
           WHEN 1 THEN '최악'
       END AS rating_label,
       COUNT(*) AS review_count,
       ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER(), 1) AS pct,
       ROUND(COUNT(title) * 100.0 / COUNT(*), 1) AS title_rate_pct
FROM reviews
GROUP BY rating
ORDER BY rating DESC;

실행 결과 (5행)

rating rating_label review_count pct title_rate_pct
5 최고 3433 40.20 80.80
4 좋음 2575 30.10 80.50
3 보통 1265 14.80 80.10
2 별로 839 9.80 80.30
1 최악 434 5.10 80.60

16. 상품의 가격대(저가/중저가/중가/고가)별로 상품 수, 평균 재고, 단종률(%)을 구하세요. 단종률은 is_a

상품의 가격대(저가/중저가/중가/고가)별로 상품 수, 평균 재고, 단종률(%)을 구하세요. 단종률은 is_active=0인 비율입니다.

힌트 1: CASE로 가격대 분류 + SUM(CASE WHEN is_active = 0 THEN 1 ELSE 0 END)로 단종 수 집계 + GROUP BY 조합입니다.

정답
SELECT CASE
           WHEN price < 100000 THEN '저가'
           WHEN price < 500000 THEN '중저가'
           WHEN price < 1000000 THEN '중가'
           ELSE '고가'
       END AS price_tier,
       COUNT(*) AS product_count,
       ROUND(AVG(stock_qty)) AS avg_stock,
       ROUND(SUM(CASE WHEN is_active = 0 THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) AS discontinued_pct
FROM products
GROUP BY price_tier
ORDER BY product_count DESC;

실행 결과 (4행)

price_tier product_count avg_stock discontinued_pct
중저가 130 277.00 23.80
고가 65 271.00 20.00
저가 47 267.00 19.10
중가 38 282.00 23.70

17. 등급별 고객 수, 평균 적립금, 성별 입력률(%), 로그인 경험률(%)을 한 번에 조회하세요. 등급 순서는

등급별 고객 수, 평균 적립금, 성별 입력률(%), 로그인 경험률(%)을 한 번에 조회하세요. 등급 순서는 VIP > GOLD > SILVER > BRONZE입니다.

힌트 1: COUNT(gender)로 성별 입력 수, COUNT(last_login_at)으로 로그인 경험 수를 구합니다. ORDER BY CASE로 등급 순서를 지정합니다.

정답
SELECT grade,
       COUNT(*) AS customer_count,
       ROUND(AVG(point_balance)) AS avg_points,
       ROUND(COUNT(gender) * 100.0 / COUNT(*), 1) AS gender_rate_pct,
       ROUND(COUNT(last_login_at) * 100.0 / COUNT(*), 1) AS login_rate_pct
FROM customers
GROUP BY grade
ORDER BY CASE grade
             WHEN 'VIP' THEN 1
             WHEN 'GOLD' THEN 2
             WHEN 'SILVER' THEN 3
             WHEN 'BRONZE' THEN 4
         END;

실행 결과 (4행)

grade customer_count avg_points gender_rate_pct login_rate_pct
VIP 368 407,015.00 96.20 100.00
GOLD 524 147,711.00 92.20 100.00
SILVER 479 95,042.00 90.60 100.00
BRONZE 3859 16,779.00 88.90 92.70

18. 주문 상태를 3그룹(처리중/완료/취소반품)으로 분류하고, 각 그룹의 건수, 총 매출, 평균 배송비, 포인트

주문 상태를 3그룹(처리중/완료/취소반품)으로 분류하고, 각 그룹의 건수, 총 매출, 평균 배송비, 포인트 사용 건수를 구하세요.

힌트 1: CASE WHEN status IN (...)로 그룹 분류. SUM(CASE WHEN point_used > 0 THEN 1 ELSE 0 END)로 포인트 사용 건수를 셉니다.

정답
SELECT CASE
           WHEN status IN ('pending', 'paid', 'preparing') THEN '처리중'
           WHEN status IN ('shipped', 'delivered', 'confirmed') THEN '완료'
           ELSE '취소/반품'
       END AS status_group,
       COUNT(*) AS order_count,
       ROUND(SUM(total_amount)) AS total_revenue,
       ROUND(AVG(shipping_fee)) AS avg_shipping,
       SUM(CASE WHEN point_used > 0 THEN 1 ELSE 0 END) AS point_used_count
FROM orders
GROUP BY status_group
ORDER BY order_count DESC;

실행 결과 (3행)

status_group order_count total_revenue avg_shipping point_used_count
완료 34,569 34,656,428,960.00 248.00 3439
취소/반품 2859 3,414,067,056.00 208.00 291
처리중 129 112,999,047.00 163.00 10

19. 카드 결제 중 카드사별 결제 건수, 평균 금액, 할부 이용률(%)을 구하세요. 카드사 정보가 NULL인 건은

카드 결제 중 카드사별 결제 건수, 평균 금액, 할부 이용률(%)을 구하세요. 카드사 정보가 NULL인 건은 제외하고, 건수가 100 이상인 카드사만 조회합니다.

힌트 1: WHERE method = 'card' AND card_issuer IS NOT NULL로 필터. SUM(CASE WHEN installment_months > 0 THEN 1 ELSE 0 END)로 할부 건수를 셉니다.

정답
SELECT card_issuer,
       COUNT(*) AS payment_count,
       ROUND(AVG(amount)) AS avg_amount,
       ROUND(SUM(CASE WHEN installment_months > 0 THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) AS installment_rate_pct
FROM payments
WHERE method = 'card'
  AND card_issuer IS NOT NULL
GROUP BY card_issuer
HAVING COUNT(*) >= 100
ORDER BY payment_count DESC;

실행 결과 (총 9행 중 상위 7행)

card_issuer payment_count avg_amount installment_rate_pct
신한카드 3375 1,011,369.00 48.80
삼성카드 2548 979,455.00 47.80
KB국민카드 2412 1,092,916.00 47.50
현대카드 1965 1,036,523.00 48.20
하나카드 1712 989,167.00 49.80
롯데카드 1692 1,018,070.00 48.70
우리카드 1391 965,158.00 47.90

20. 공급업체별 상품 수와 활성 상품 비율(%)을 구하세요. 상품 수가 3개 이상인 공급업체만 대상이며, 활성 비

공급업체별 상품 수와 활성 상품 비율(%)을 구하세요. 상품 수가 3개 이상인 공급업체만 대상이며, 활성 비율이 높은 순으로 정렬합니다. 공급업체는 supplier_id로 그룹화합니다.

힌트 1: GROUP BY supplier_id + HAVING COUNT(*) >= 3 + SUM(CASE WHEN is_active = 1 ...)로 활성 비율 계산 + ORDER BY 조합입니다.

정답
SELECT supplier_id,
       COUNT(*) AS product_count,
       SUM(CASE WHEN is_active = 1 THEN 1 ELSE 0 END) AS active_count,
       ROUND(SUM(CASE WHEN is_active = 1 THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) AS active_rate_pct
FROM products
GROUP BY supplier_id
HAVING COUNT(*) >= 3
ORDER BY active_rate_pct DESC;

실행 결과 (총 32행 중 상위 7행)

supplier_id product_count active_count active_rate_pct
2 11 11 100.00
17 6 6 100.00
22 3 3 100.00
24 5 5 100.00
36 11 11 100.00
37 5 5 100.00
27 13 12 92.30

21. 브랜드별 활성 상품 수와 평균 가격을 구하되, 평균 가격 100만원 이상인 브랜드만 조회하세요. 가격대 분류

브랜드별 활성 상품 수와 평균 가격을 구하되, 평균 가격 100만원 이상인 브랜드만 조회하세요. 가격대 분류(프리미엄/대중/보급형)도 함께 표시합니다.

힌트 1: WHERE is_active = 1 + GROUP BY brand + HAVING AVG(price) >= 1000000 + CASE로 가격대 분류 조합입니다.

정답
SELECT brand,
       COUNT(*) AS active_product_count,
       ROUND(AVG(price)) AS avg_price,
       CASE
           WHEN AVG(price) >= 2000000 THEN '프리미엄'
           WHEN AVG(price) >= 1000000 THEN '대중'
           ELSE '보급형'
       END AS brand_tier
FROM products
WHERE is_active = 1
GROUP BY brand
HAVING AVG(price) >= 1000000
ORDER BY avg_price DESC;

실행 결과 (총 8행 중 상위 7행)

brand active_product_count avg_price brand_tier
Apple 2 2,815,400.00 프리미엄
Razer 7 1,996,443.00 대중
레노버 2 1,695,450.00 대중
주연테크 3 1,614,633.00 대중
ASUS 21 1,589,552.00 대중
BenQ 1 1,476,300.00 대중
HP 5 1,433,140.00 대중

22. 2024년 월별 매출 분석: 월별 주문 건수, 총 매출, 평균 주문 금액, 취소율(%), 무료배송 비율(%)

2024년 월별 매출 분석: 월별 주문 건수, 총 매출, 평균 주문 금액, 취소율(%), 무료배송 비율(%)을 구하세요.

힌트 1: 다양한 집계를 조합합니다. 취소율 = COUNT(cancelled_at) / COUNT(*). 무료배송 = shipping_fee = 0인 건의 비율입니다.

정답
SELECT SUBSTR(ordered_at, 1, 7) AS month,
       COUNT(*) AS order_count,
       ROUND(SUM(total_amount)) AS total_revenue,
       ROUND(AVG(total_amount)) AS avg_amount,
       ROUND(COUNT(cancelled_at) * 100.0 / COUNT(*), 1) AS cancel_rate_pct,
       ROUND(SUM(CASE WHEN shipping_fee = 0 THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) AS free_ship_pct
FROM orders
WHERE ordered_at LIKE '2024%'
GROUP BY month
ORDER BY month;

실행 결과 (총 12행 중 상위 7행)

month order_count total_revenue avg_amount cancel_rate_pct free_ship_pct
2024-01 346 320,292,182.00 925,700.00 6.10 91.30
2024-02 465 449,447,834.00 966,554.00 6.90 92.30
2024-03 601 569,798,709.00 948,084.00 4.80 93.30
2024-04 506 496,023,258.00 980,283.00 5.50 94.50
2024-05 415 473,243,857.00 1,140,347.00 4.60 94.00
2024-06 415 399,487,004.00 962,619.00 4.30 93.70
2024-07 414 383,398,728.00 926,084.00 5.60 93.50

23. 고객 세그먼트 분석: 등급과 활동 상태(활동/휴면/탈퇴)를 조합하여 세그먼트별 고객 수와 평균 적립금을 구하

고객 세그먼트 분석: 등급과 활동 상태(활동/휴면/탈퇴)를 조합하여 세그먼트별 고객 수와 평균 적립금을 구하세요. 고객 수 100명 이상인 세그먼트만 조회합니다.

힌트 1: CASE로 활동 상태(is_active=0이면 탈퇴, last_login_at IS NULL이면 휴면, 그 외 활동) 분류. GROUP BY grade, activity_status 조합입니다.

정답
SELECT grade,
       CASE
           WHEN is_active = 0 THEN '탈퇴'
           WHEN last_login_at IS NULL THEN '휴면'
           ELSE '활동'
       END AS activity_status,
       COUNT(*) AS customer_count,
       ROUND(AVG(point_balance)) AS avg_points
FROM customers
GROUP BY grade, activity_status
HAVING COUNT(*) >= 100
ORDER BY CASE grade
             WHEN 'VIP' THEN 1
             WHEN 'GOLD' THEN 2
             WHEN 'SILVER' THEN 3
             WHEN 'BRONZE' THEN 4
         END,
         customer_count DESC;

실행 결과 (6행)

grade activity_status customer_count avg_points
VIP 활동 368 407,015.00
GOLD 활동 524 147,711.00
SILVER 활동 479 95,042.00
BRONZE 활동 2100 30,834.00
BRONZE 탈퇴 1570 0.0
BRONZE 휴면 189 0.0

24. 상품 데이터 품질 리포트: 브랜드별로 상품 수, 설명 누락률(%), 사양 누락률(%), 무게 누락률(%)을

상품 데이터 품질 리포트: 브랜드별로 상품 수, 설명 누락률(%), 사양 누락률(%), 무게 누락률(%)을 구하세요. 상품 수 10개 이상인 브랜드만 대상이며, 전체 누락률(3개 평균)이 높은 순으로 정렬합니다.

힌트 1: (COUNT(*) - COUNT(칼럼)) * 100.0 / COUNT(*)로 각 칼럼의 누락률을 구합니다. 3개의 누락률 평균으로 정렬합니다.

정답
SELECT brand,
       COUNT(*) AS product_count,
       ROUND((COUNT(*) - COUNT(description)) * 100.0 / COUNT(*), 1) AS desc_missing_pct,
       ROUND((COUNT(*) - COUNT(specs)) * 100.0 / COUNT(*), 1) AS specs_missing_pct,
       ROUND((COUNT(*) - COUNT(weight_grams)) * 100.0 / COUNT(*), 1) AS weight_missing_pct
FROM products
GROUP BY brand
HAVING COUNT(*) >= 10
ORDER BY (
    (COUNT(*) - COUNT(description)) +
    (COUNT(*) - COUNT(specs)) +
    (COUNT(*) - COUNT(weight_grams))
) * 1.0 / COUNT(*) DESC;

실행 결과 (7행)

brand product_count desc_missing_pct specs_missing_pct weight_missing_pct
로지텍 17 0.0 100.00 0.0
TP-Link 11 0.0 100.00 0.0
ASRock 11 0.0 100.00 0.0
MSI 13 0.0 61.50 0.0
ASUS 26 0.0 30.80 0.0
삼성전자 25 0.0 24.00 0.0
LG전자 11 0.0 0.0 0.0

25. 연도별 고객 가입 분석: 가입 연도별 고객 수, 성별 비율(남/여/미입력), 평균 적립금을 구하세요.

연도별 고객 가입 분석: 가입 연도별 고객 수, 성별 비율(남/여/미입력), 평균 적립금을 구하세요.

힌트 1: SUM(CASE WHEN gender = 'M' THEN 1 ELSE 0 END) * 100.0 / COUNT(*)로 남성 비율을 구합니다. 성별 NULL도 별도 비율로 계산합니다.

정답
SELECT SUBSTR(created_at, 1, 4) AS join_year,
       COUNT(*) AS customer_count,
       ROUND(SUM(CASE WHEN gender = 'M' THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) AS male_pct,
       ROUND(SUM(CASE WHEN gender = 'F' THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) AS female_pct,
       ROUND(SUM(CASE WHEN gender IS NULL THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) AS unknown_pct,
       ROUND(AVG(point_balance)) AS avg_points
FROM customers
GROUP BY join_year
ORDER BY join_year;

실행 결과 (총 10행 중 상위 7행)

join_year customer_count male_pct female_pct unknown_pct avg_points
2016 100 53.00 29.00 18.00 212,578.00
2017 180 57.20 32.20 10.60 170,364.00
2018 300 56.30 32.00 11.70 144,012.00
2019 450 56.90 32.70 10.40 99,968.00
2020 700 61.60 28.70 9.70 94,152.00
2021 800 56.30 33.00 10.80 69,793.00
2022 650 60.60 30.30 9.10 53,009.00

26. 할인 분석: 2024년 주문에서 할인 적용 여부(할인있음/할인없음)와 금액 구간(소액/일반/고액/VIP급)을

할인 분석: 2024년 주문에서 할인 적용 여부(할인있음/할인없음)와 금액 구간(소액/일반/고액/VIP급)을 조합하여 건수와 평균 주문 금액을 구하세요.

힌트 1: CASE WHEN discount_amount > 0로 할인 여부, CASE WHEN total_amount < 50000으로 금액 구간을 분류합니다. GROUP BY에 두 CASE를 모두 사용합니다.

정답
SELECT CASE WHEN discount_amount > 0 THEN '할인있음' ELSE '할인없음' END AS has_discount,
       CASE
           WHEN total_amount < 50000 THEN '소액'
           WHEN total_amount < 200000 THEN '일반'
           WHEN total_amount < 1000000 THEN '고액'
           ELSE 'VIP급'
       END AS amount_tier,
       COUNT(*) AS order_count,
       ROUND(AVG(total_amount)) AS avg_amount
FROM orders
WHERE ordered_at LIKE '2024%'
GROUP BY has_discount, amount_tier
ORDER BY has_discount, avg_amount DESC;

실행 결과 (총 8행 중 상위 7행)

has_discount amount_tier order_count avg_amount
할인없음 VIP급 1314 2,190,896.00
할인없음 고액 1498 447,381.00
할인없음 일반 1435 121,632.00
할인없음 소액 276 36,244.00
할인있음 VIP급 652 2,567,481.00
할인있음 고액 398 481,555.00
할인있음 일반 173 125,703.00

27. 카테고리별 상품 현황: category_id별 전체 상품 수, 판매중 수, 단종 수, 품절 수, 평균 가격을

카테고리별 상품 현황: category_id별 전체 상품 수, 판매중 수, 단종 수, 품절 수, 평균 가격을 구하세요. 전체 상품 수가 5개 이상인 카테고리만 대상입니다.

힌트 1: SUM(CASE WHEN 조건 THEN 1 ELSE 0 END)로 각 상태의 수를 별도 칼럼으로 집계합니다.

정답
SELECT category_id,
       COUNT(*) AS total,
       SUM(CASE WHEN is_active = 1 THEN 1 ELSE 0 END) AS active_count,
       SUM(CASE WHEN is_active = 0 THEN 1 ELSE 0 END) AS discontinued_count,
       SUM(CASE WHEN stock_qty = 0 THEN 1 ELSE 0 END) AS out_of_stock,
       ROUND(AVG(price)) AS avg_price
FROM products
GROUP BY category_id
HAVING COUNT(*) >= 5
ORDER BY total DESC;

실행 결과 (총 31행 중 상위 7행)

category_id total active_count discontinued_count out_of_stock avg_price
18 13 10 3 0 529,754.00
30 13 11 2 0 219,008.00
43 12 9 3 0 277,150.00
3 11 9 2 0 1,719,809.00
31 11 10 1 0 158,482.00
36 11 8 3 0 158,000.00
37 11 7 4 0 41,064.00

28. 결제 수단 종합 분석: 수단별(한글 표시) 건수, 총 금액, 평균 금액, 환불 건수, 환불률(%)을 구하세요

결제 수단 종합 분석: 수단별(한글 표시) 건수, 총 금액, 평균 금액, 환불 건수, 환불률(%)을 구하세요. 건수가 1,000건 이상인 수단만 대상입니다.

힌트 1: CASE로 수단 한글화 + COUNT(refunded_at)으로 환불 건수 + HAVING + ORDER BY 조합입니다.

정답
SELECT CASE method
           WHEN 'card' THEN '신용카드'
           WHEN 'bank_transfer' THEN '계좌이체'
           WHEN 'virtual_account' THEN '가상계좌'
           WHEN 'kakao_pay' THEN '카카오페이'
           WHEN 'naver_pay' THEN '네이버페이'
           WHEN 'point' THEN '포인트'
       END AS method_kr,
       COUNT(*) AS payment_count,
       ROUND(SUM(amount)) AS total_amount,
       ROUND(AVG(amount)) AS avg_amount,
       COUNT(refunded_at) AS refund_count,
       ROUND(COUNT(refunded_at) * 100.0 / COUNT(*), 1) AS refund_rate_pct
FROM payments
GROUP BY method
HAVING COUNT(*) >= 1000
ORDER BY total_amount DESC;

실행 결과 (6행)

method_kr payment_count total_amount avg_amount refund_count refund_rate_pct
신용카드 16,841 17,004,951,634.00 1,009,735.00 872 5.20
카카오페이 7486 7,563,829,668.00 1,010,397.00 380 5.10
네이버페이 5715 5,998,835,720.00 1,049,665.00 285 5.00
계좌이체 3718 3,753,149,013.00 1,009,454.00 178 4.80
포인트 1921 1,951,369,604.00 1,015,809.00 98 5.10
가상계좌 1876 1,911,359,424.00 1,018,848.00 117 6.20

29. 고객 프로필 완성도 분석: 완성도 점수(0~4점)별 고객 수, 비율(%), 평균 적립금, VIP 비율(%)을

고객 프로필 완성도 분석: 완성도 점수(0~4점)별 고객 수, 비율(%), 평균 적립금, VIP 비율(%)을 구하세요. 완성도 = birth_date, gender, last_login_at, acquisition_channel 중 NULL이 아닌 수.

힌트 1: (칼럼 IS NOT NULL)은 SQLite에서 1 또는 0을 반환합니다. 4개를 더해 완성도 점수를 구합니다.

정답
SELECT (birth_date IS NOT NULL)
     + (gender IS NOT NULL)
     + (last_login_at IS NOT NULL)
     + (acquisition_channel IS NOT NULL) AS completeness,
       COUNT(*) AS customer_count,
       ROUND(AVG(point_balance)) AS avg_points,
       ROUND(SUM(CASE WHEN grade = 'VIP' THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) AS vip_rate_pct
FROM customers
GROUP BY completeness
ORDER BY completeness;

실행 결과 (4행)

completeness customer_count avg_points vip_rate_pct
1 5 0.0 0.0
2 143 20,877.00 0.7
3 1247 45,918.00 4.30
4 3835 72,285.00 8.20

30. 종합 대시보드: 상품 테이블에서 브랜드별 활성 상품 수, 평균 가격, 평균 마진율(%), 가격대 분류, 재고

종합 대시보드: 상품 테이블에서 브랜드별 활성 상품 수, 평균 가격, 평균 마진율(%), 가격대 분류, 재고 부족 상품 수(stock_qty <= 10)를 구하세요. 활성 상품 5개 이상인 브랜드만 대상이며, 활성 상품 수 내림차순으로 상위 10개만 조회합니다.

힌트 1: 여러 집계와 CASE를 동시에 사용합니다. WHERE is_active = 1 + GROUP BY brand + HAVING + ORDER BY + LIMIT 조합입니다.

정답
SELECT brand,
       COUNT(*) AS active_count,
       ROUND(AVG(price)) AS avg_price,
       ROUND(AVG((price - cost_price) * 100.0 / price), 1) AS avg_margin_pct,
       CASE
           WHEN AVG(price) >= 1000000 THEN '프리미엄'
           WHEN AVG(price) >= 300000 THEN '대중'
           ELSE '보급형'
       END AS brand_tier,
       SUM(CASE WHEN stock_qty <= 10 THEN 1 ELSE 0 END) AS low_stock_count
FROM products
WHERE is_active = 1
GROUP BY brand
HAVING COUNT(*) >= 5
ORDER BY active_count DESC
LIMIT 10;

실행 결과 (총 10행 중 상위 7행)

brand active_count avg_price avg_margin_pct brand_tier low_stock_count
삼성전자 21 641,800.00 18.50 대중 1
ASUS 21 1,589,552.00 28.00 프리미엄 0
MSI 12 820,292.00 16.80 대중 0
로지텍 11 115,127.00 28.00 보급형 1
TP-Link 11 128,764.00 30.30 보급형 0
LG전자 11 1,346,836.00 21.20 프리미엄 0
ASRock 9 493,244.00 25.60 대중 0