티스토리 뷰

SQL 코드카타

Q21. 이름이 없는 동물의 아이디

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/59039

2. 정답 코드:

SELECT ANIMAL_ID
FROM ANIMAL_INS
WHERE NAME IS NULL
ORDER BY ANIMAL_ID ASC;

 

Q22. 조건에 맞는 회원수 구하기

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/131535

2. 정답 코드:

SELECT COUNT(*) AS USERS
FROM USER_INFO
WHERE SUBSTR(JOINED, 1, 4) = '2021'
  AND AGE BETWEEN 20 AND 29;

 

Q23. 중성화 여부 파악하기

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/59409

2. 정답 코드:

SELECT
    ANIMAL_ID,
    NAME,
    CASE
        WHEN SEX_UPON_INTAKE LIKE 'Neutered%' THEN 'O'
        WHEN SEX_UPON_INTAKE LIKE 'Spayed%' THEN 'O'
        ELSE 'X'
    END AS '중성화'
FROM ANIMAL_INS;

3. 오류 상황: 중성화 컬럼의 모든 값이 X로 나옴

4. 시도 방법: 사용한 문법이 잘못 되었는지 확인함

5. 최종 문제 해결 방법:

'Neutered%' 이런 식으로 특정 단어를 포함한 형태를 찾으려면 LIKE를 사용해야 하는데, LIKE는 IN (a, b) 구문과 달리 두 가지 조건을 한 번에 줄 수 없다!
→ CASE WHEN LIKE 1 THEN 'O'
               WHEN LIKE 2 THEN 'O'
               ELSE 'X'
     END AS '별칭'
이런 식으로 각각의 조건을 하나씩 줘야만 구현 가능하다!

 

Q24. 카테고리 별 상품 개수 구하기

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/131529

2. 정답 코드:

SELECT
    SUBSTR(PRODUCT_CODE, 1, 2) AS CATEGORY,  
    COUNT(*) AS PRODUCTS
FROM PRODUCT
GROUP BY SUBSTR(PRODUCT_CODE, 1, 2) 
ORDER BY CATEGORY ASC;

 

Q25. 고양이와 개는 몇 마리 있을까

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/59040

2. 정답 코드:

SELECT
    ANIMAL_TYPE,
    COUNT(*) AS count
FROM ANIMAL_INS
WHERE ANIMAL_TYPE IN ('Cat', 'Dog')
GROUP BY ANIMAL_TYPE
ORDER BY ANIMAL_TYPE ASC;

 

Q26. 입양 시각 구하기(1)

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/59412

2. 정답 코드:

SELECT
    SUBSTR(DATETIME, 12, 2) AS HOUR,
    COUNT(*) AS COUNT
FROM ANIMAL_OUTS
WHERE SUBSTR(DATETIME, 12, 2) >= 09
  AND SUBSTR(DATETIME, 12, 2) < 20
GROUP BY SUBSTR(DATETIME, 12, 2)
ORDER BY HOUR ASC;


Q27. 진료과별 총 예약 횟수 출력하기

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/132202

2. 정답 코드:

SELECT
    MCDP_CD AS 진료과코드,
    COUNT(*) AS 5월예약건수
FROM APPOINTMENT
WHERE SUBSTR(APNT_YMD, 1, 7) = '2022-05'
GROUP BY MCDP_CD
ORDER BY 5월예약건수 ASC, 진료과코드 ASC;


Q28. 12세 이하인 여자 환자 목록 출력하기

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/132201

2. 정답 코드:

SELECT
    PT_NAME,
    PT_NO,
    GEND_CD,
    AGE,
    CASE
        WHEN TLNO IS NULL THEN 'NONE'
        ELSE TLNO
    END AS TLNO
FROM PATIENT
WHERE AGE <= 12
  AND GEND_CD = 'W'
ORDER BY AGE DESC, PT_NAME ASC;

 

Q29. 인기있는 아이스크림

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/133024

2. 정답 코드:

SELECT FLAVOR
FROM FIRST_HALF
ORDER BY TOTAL_ORDER DESC, SHIPMENT_ID ASC;


Q30. 자동차 종류 별 특정 옵션이 포함된 자동차 수 구하기

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/151137

2. 정답 코드:

SELECT
    CAR_TYPE,
    COUNT(*) AS CARS
FROM CAR_RENTAL_COMPANY_CAR
WHERE OPTIONS LIKE '%시트%'
GROUP BY CAR_TYPE
ORDER BY CAR_TYPE ASC;

SQL 성취도 평가

Q1. SQL의 “논리 실행 순서(작동 순서)”로 가장 올바른 것은? 🧰 필수

A. SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY
B. WHERE → FROM → GROUP BY → SELECT → HAVING → ORDER BY
C. FROM → ON/JOIN → WHERE → GROUP BY → HAVING → SELECT → DISTINCT → ORDER BY
D. FROM → SELECT → WHERE → ORDER BY → GROUP BY → HAVING


Q2. 아래 테이블에서 COUNT() 결과로 올바른 것은? 🧰 필수

  • 테이블: t_review
id  review_score
1 5
2 NULL
3 3
  • 쿼리:
SELECT 
  COUNT(*) AS c1,
  COUNT(review_score) AS c2,
  COUNT(DISTINCT review_score) AS c3
FROM t_review;

 

A. (3, 2, 2)

B. (3, 3, 2)

C. (2, 2, 2)

D. (3, 2, 3)

COUNT(*)만 NULL 값까지 셈
COUNT(컬럼명) 사용 시에는 NULL 값 제외한 행 수만 COUNT
COUNT(DISTINCT 컬럼명) 사용 시에는 NULL 값 제외하고, 고유값만 COUNT

Q3. 아래 쿼리가 에러(혹은 비결정적 결과)를 유발하는 가장 적절한 이유는? 🧰 필수

SELECT
  ship_region,
  order_date,
  COUNT(*) AS order_cnt
FROM orders
GROUP BY ship_region;

A. COUNT(*)는 GROUP BY와 함께 쓸 수 없다

A. COUNT(*)는 GROUP BY와 함께 쓸 수 없다

B. ship_region은 GROUP BY에 사용할 수 없다

C. order_date는 반드시 ORDER BY에 있어야 한다

D. SELECT에 있는 비집계 컬럼(order_date)이 GROUP BY에 포함되지 않았다

GROUP BY를 사용하면 여러 개의 행이 하나의 행으로 합쳐지는데,
이때 집계 함수(
SUM, AVG, COUNT 등)를 쓰지 않은 컬럼은 어떤 값을 보여줘야 할지 알 수 없는 상태가 됨
→ 기준을 만들어주기 위해서 출력을 원하는 컬럼 중에서 집계 함수가 없는 컬럼은 GROUP BY에 꼭 명시해줘야 함!

Q4. GROUP BY가 있는 쿼리에서 집계 전에 행을 먼저 필터링하려면 어느 절을 사용하는 것이 가장 적절한가? 🧰 필수

A. HAVING

B. WHERE

C. ORDER BY

D. LIMIT

문제가 약간 헷갈릴 수도 있는데, GROUP BY가 나왔다고 바로 HAVING을 고르면 안되고
집계 전에 행을 먼저 필터링 한다고 했으니, WHERE절이 맞음!

Q5. UNION과 UNION ALL의 차이로 올바른 것은? 🧰 필수 

A. UNION은 열을 늘리고 UNION ALL은 행을 늘린다

B. UNION ALL은 중복을 제거하고 UNION은 중복을 유지한다

C. UNION은 중복 행을 제거하고, UNION ALL은 중복 행을 유지한다

D. UNION은 ORDER BY를 절대 사용할 수 없다


Q6. 아래 쿼리가 LEFT JOIN임에도 불구하고 결과가 “INNER JOIN처럼” 보일 가능성이 가장 큰 이유는? 🚀 도전

SELECT o.order_id, p.payment_id
FROM orders o
LEFT JOIN payments p
  ON o.order_id = p.order_id
WHERE p.payment_status = 'paid';

A. LEFT JOIN은 원래 매칭 없는 행을 못 가져온다

B. ON절에는 조건을 추가할 수 없다

C. WHERE절은 조인 조건을 무시한다

D. WHERE절이 오른쪽 테이블 NULL 행을 제거해서 결과가 INNER JOIN처럼 된다


Q7. 아래 데이터에서 CASE 결과로 올바른 것은? 🧰 필수

  • 테이블 일부: orders
order_id coupon_code
ord_5001 NEW10
ord_5002 NULL
ord_5008 VIP15
  • 쿼리:
SELECT
  order_id,
  CASE
    WHEN coupon_code IS NULL THEN 'no_coupon'
    WHEN coupon_code = 'VIP15' THEN 'vip'
    ELSE 'other_coupon'
  END AS coupon_label
FROM orders
WHERE order_id IN ('ord_5001','ord_5002','ord_5008')
ORDER BY order_id;

A. ord_5001=other_coupon / ord_5002=no_coupon / ord_5008=vip

B. ord_5001=vip / ord_5002=no_coupon / ord_5008=other_coupon

C. ord_5001=no_coupon / ord_5002=other_coupon / ord_5008=vip

D. ord_5001=other_coupon / ord_5002=vip / ord_5008=no_coupon


Q8. IN(subquery)를 사용할 때 가장 안전한 조건으로 올바른 것은? 🚀 도전

A. subquery는 반드시 1행만 반환해야 한다 → 스칼라 서브쿼리도 있지만, 리스트 서브쿼리 등 여러 행으로 반환되는 것도 있음

B. subquery는 보통 1개 컬럼(값 목록)을 반환해야 한다

C. subquery에는 GROUP BY가 반드시 있어야 한다 없어도 됨

D. subquery에는 WHERE를 쓰면 안 된다 사용 가능


Q9. CTE(WITH)에 대한 설명으로 가장 올바른 것은? 🧰 필수

A. 실행하면 DB에 영구 테이블로 저장된다   일시적으로 사용하는 사용자 함수 개념

B. 항상 GROUP BY가 포함되어야 한다   없어도 됨

C. JOIN과 함께 사용 불가능하다   CTE는 주로 JOIN과 사용해서 쿼리를 단순화 함

D. 단일 statement 범위에서만 존재하며, 그 statement 안에서 여러 번 참조 가능하다


Q10. MySQL에서 윈도우 함수 사용 위치로 올바른 것은? 🚀 도전

A. WHERE 절에서만 사용 가능

B. GROUP BY 절에서만 사용 가능

C. SELECT 리스트와 ORDER BY 절에서만 사용 가능

D. JOIN ON 절에서만 사용 가능


Q11. 주문 리스트 라벨링 🧰 필수

orders 테이블에서 아래 조건을 만족하는 주문만 출력하세요.

 

조건

  • order_date가 '2026-01-05' ~ '2026-01-15' (포함)

출력 컬럼

  • order_id
  • order_date
  • channel
  • order_status
  • coupon_flag
    • coupon_code가 NULL이면 'no_coupon'
    • 아니면 'coupon_used'
  • delivery_days_clean
    • delivery_days가 NULL이면 0, 아니면 delivery_days

정렬

  • order_date 오름차순, order_id 오름차순
SELECT
	order_id,
	order_date,
	channel,
	order_status,
	CASE
		WHEN coupon_code IS NULL THEN 'no_coupon'
	ELSE 'coupon_used'
	END AS coupon_flag,
	CASE
		WHEN delivery_days IS NULL THEN 0
	ELSE delivery_days
	END AS delivery_days_clean	
FROM sqltest.orders
WHERE order_date BETWEEN '2026-01-05' AND '2026-01-15'
ORDER BY order_date ASC, order_id ASC;
[튜터님 피드백]
WHERE order_date >= '2026-01-05' and order_date < '2026-01-16' 으로 해야 함!
→ BETWEEN '2026-01-05' AND '2026-01-15' 로 하게 되면, '2026-01-15 00:00:00' 이후의 데이터들은 다 짤리게 됨
    여기서는 결과 출력에 문제가 없었지만 나중에는 < '2026-01-16'로 작성하기

+ 내가 추가
IFNULL(delivery_days, 0) as delivery_days_clean 해도 됨

Q12. 지역별 매출 요약 🧰 필수

orders + order_items를 이용해서, 완료된 주문만 지역별로 요약하세요.

 

조건

  • order_status = 'completed'

매출(net_revenue) 정의

  • unit_price * quantity * (1 - discount_rate)

출력 컬럼

  • ship_region
  • order_cnt : 지역별 고유 주문 수
  • customer_cnt : 지역별 고유 고객 수
  • net_revenue : 지역별 매출 합계

추가 조건(HAVING)

  • order_cnt >= 2 인 지역만
  •  

정렬

  • net_revenue 내림차순, ship_region 오름차순

참고

  • orders 테이블 별칭 : o / order_items 테이블 별칭 : oi
SELECT
	o.ship_region,
	count(DISTINCT o.order_id) AS order_cnt,
	count(DISTINCT o.customer_id) AS customer_cnt,
	sum(oi.unit_price * oi.quantity * (1 - oi.discount_rate)) AS net_revenue
FROM sqltest.orders o 
INNER JOIN sqltest.order_items oi
  ON o.order_id = oi.order_id 
WHERE o.order_status = 'completed'
GROUP BY o.ship_region 
HAVING count(DISTINCT o.order_id) >= 2
ORDER BY net_revenue DESC, ship_region ASC;
[튜터님 피드백]
oi.discount_rate가 소수점으로 표시되는 컬럼이기 때문에, 이 값을 가지고 구하는 net_revenue 는 소수점 처리를 해줘야 함!
지금 결과 상으로는 이상이 없어 보이지만 나중에는 문제가 될 수 있으므로, 
sum(oi.unit_price * oi.quantity * (1 - oi.discount_rate)) AS net_revenue
→ ROUND(sum(oi.unit_price * oi.quantity * (1 - oi.discount_rate)), 0) AS net_revenue
소수점 자릿수 지정해주기!!!

Q13. 결제 내역 붙이기 🚀 도전

orders를 기준으로 결제 정보를 붙이되, 결제가 없는 주문도 결과에 남겨야 합니다.

 

상 주문

  • 대상 주문: order_date가 '2026-01-05' ~ '2026-01-31' (포함)
  • payments는 payment_status='paid' 인 결제만 붙이세요.

출력 컬럼

  • order_id, order_status, order_date
  • payment_id, paid_at, amount (결제 없으면 NULL)

정렬

  • order_date, order_id, paid_at 오름차순

참고

  • orders 테이블 별칭 : o   /  payments 테이블 별칭 : p
SELECT
	o.order_id,
	o.order_status,
	o.order_date,
	p.payment_id,
	p.paid_at,
	p.amount 
FROM sqltest.orders o 
LEFT JOIN sqltest.payments p
  ON o.order_id = p.order_id
  AND p.payment_status = 'paid'
WHERE o.order_date BETWEEN '2026-01-05' AND '2026-01-31'
ORDER BY o.order_date ASC, o.order_id ASC, p.paid_at ASC;

 

[튜터님 피드백]
WHERE o.order_date >= '2026-01-05' and o.order_date < '2026-02-01' 로 해야 함!
→ BETWEEN '2026-01-05' AND '2026-01-31' 로 하게 되면, '2026-01-31 00:00:00' 이후의 데이터들은 다 짤리게 됨
    여기서는 결과 출력에 문제가 없었지만 나중에는 < '2026-02-01'로 작성하기

Q14. SQL 카테고리 구매 고객 찾기 🚀 도전

아래 조건을 만족하는 고객을 찾으세요.

조건

  • 고객이 completed 주문을 한 적이 있고
  • 그 주문에 포함된 책 중 books.category = 'sql' 이 하나라도 포함

출력 컬럼

  • customer_id, customer_name, segment

정렬

  • customer_id 오름차순

참고

  • orders 테이블 별칭 : o   /  order_items 테이블 별칭 : oi  / books 테이블 별칭 : b / customers 테이블 별칭 c
  • 힌트: EXISTS 또는 IN 방식 둘 다 허용
SELECT
	c.customer_id,
	c.customer_name,
	c.segment
FROM sqltest.customers c
WHERE c.customer_id IN (
	SELECT o.customer_id  
	FROM sqltest.orders o 
	WHERE o.order_status = 'completed'
	  AND o.order_id IN (
	  	SELECT oi.order_id 
	  	FROM sqltest.order_items oi 
	  	INNER JOIN sqltest.books b 
	  	  ON oi.book_id = b.book_id 
	  	  AND b.category = 'sql'
	  )
)
ORDER BY c.customer_id ASC;

# IN 구문 2번 사용 - 제출 Ver.

select
	c.customer_id,
	c.customer_name,
	c.segment
from customers c
where exists (
	select 1
	from orders o
	join order_items oi
		on o.order_id = oi.order_id
	join books b
		on b.book_id = oi.book_id
	where o.customer_id = c.customer_id
		and o.order_status = 'completed'
		and b.category = 'sql'
)
order by c.customer_id;

# EXISTS 구문 사용 - 세션 Ver.


Q15. 고객별 주문 수를 행 유지로 붙이기 🚀 도전

✅orders에서 각 주문 행(행 유지)마다, 해당 고객의 주문 수를 붙여 출력하세요.

출력 컬럼

  • order_id, customer_id, order_date, order_status
  • customer_order_cnt : 고객별 주문 수

정렬

  • customer_id, order_date, order_id 오름차순
SELECT
	order_id,
	customer_id,
	order_date,
	order_status,
	count(*) OVER (PARTITION BY customer_id) AS customer_order_cnt
FROM sqltest.orders
ORDER BY customer_id ASC, order_date ASC, order_id ASC;
행 유지 = 윈도우 함수

라이브 세션) 파이썬 기초 학습을 위한 OT

데이터 분석에서 코딩은,
데이터를 읽고 → 정리하고 → 요약하고 → 시각화하는 과정

 

  • 세션 학습 전, 학습 토픽 및 주요 용어 사전 파악 필요
  • Line by Line으로 코드를 설명할 수 있어야 한다!

수도코드(의사코드, Pseudo Code)

: 자연어(사람의 말)를 이용해 만든 문장을 프로그래밍 언어와 유사한 형식으로 배치한 코드

→ 생각(순서)만 먼저 정리할 수 있음


8일 동안 SQL 기초를 학습하며, SQL과 친해진 것 같은 느낌이다!
성취도 평가는 시간도 촉박하고 쉽진 않았지만, 그래도 모든 쿼리를 직접 작성해 제출해서 뿌듯했다.
다만 오늘 목표했던 SQL 복습은 시간 부족으로 진행하지 못해 주말을 활용해서 추가로 공부할 예정이다.
다음 주부터 시작되는 Python 강의도 진도를 놓치지 않고 따라갈 수 있도록 문길래 튜터님께서 말씀해주신 것처럼 미리 모르는 용어나 토픽을 파악해보는 시간을 가져야겠다.
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/05   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함