1 문제 1: 렌탈 요금 평균 조회
1.1 문제 정보
| 항목 | 내용 |
|---|---|
| 출처 | 튜터 생성 (앵커: Programmers “평균 일일 대여 요금 구하기” Lv.1) |
| 난이도 | Level 1 |
| SQL 유형 | AVG, ROUND |
1.2 문제 설명
CREATE TABLE RENTAL_INFO (
rental_id INT PRIMARY KEY,
car_type VARCHAR(20),
daily_fee INT,
rental_days INT
);
INSERT INTO RENTAL_INFO VALUES
(1, 'SUV', 15000, 3),
(2, 'SEDAN', 12000, 5),
(3, 'SUV', 18000, 2),
(4, 'SEDAN', 10000, 7),
(5, 'SUV', 20000, 1);RENTAL_INFO 테이블에서 전체 차량의 평균 일일 렌탈 요금을 소수점 첫째 자리에서 반올림하여 AVG_FEE로 조회하라.
기대 결과:
| AVG_FEE |
|---|
| 15000 |
1.3 최종 풀이
AVG(daily_fee): 전체 일일 요금 합계 ÷ 행 수ROUND(..., 0): 소수점 0자리, 즉 정수로 반올림
1.4 Tips
- 핵심 개념:
AVG()집계 함수,ROUND(값, 자릿수) - 함정: 문제가 요구하는 컬럼을 정확히 특정해야 한다.
daily_fee * rental_days는 총액이지 단가가 아니다. - 팁: 집계 결과에 소수점이 나오면
ROUND()로 감싸는 패턴을 습관화한다.
2 문제 2: 메뉴 종류 수 조회
2.1 문제 정보
| 항목 | 내용 |
|---|---|
| 출처 | 튜터 생성 (앵커: Programmers “조건에 맞는 도서 리스트 출력하기” 계열) |
| 난이도 | Level 1 |
| SQL 유형 | COUNT, DISTINCT, WHERE, NULL 처리 |
2.2 문제 설명
CREATE TABLE food_order (
order_id INT PRIMARY KEY,
restaurant VARCHAR(50),
menu_item VARCHAR(50),
order_date DATE
);
INSERT INTO food_order VALUES
(1, '맛있는치킨', '후라이드', '2024-03-01'),
(2, '맛있는치킨', '양념치킨', '2024-03-02'),
(3, '맛있는치킨', '후라이드', '2024-03-03'),
(4, '맛있는치킨', NULL, '2024-03-04'),
(5, '최고피자', '페퍼로니', '2024-03-01'),
(6, '최고피자', '마르게리타', '2024-03-02'),
(7, '맛있는치킨', '간장치킨', '2024-03-05');맛있는치킨 레스토랑에서 주문된 고유 메뉴 종류 수를 menu_count로 조회하라. NULL 메뉴는 제외한다.
기대 결과:
| menu_count |
|---|
| 3 |
2.3 최종 풀이
DISTINCT menu_item: 중복 메뉴를 제거한 후 카운트COUNT()는 NULL을 자동으로 제외하므로 별도의IS NOT NULL조건이 불필요하다
2.4 Tips
- 핵심 개념:
COUNT(DISTINCT 컬럼), NULL 자동 제외 동작 - 함정: WHERE 조건 누락 — 집계 전에 범위를 먼저 좁혀야 한다.
- 팁:
COUNT(컬럼)은 NULL을 세지 않는다.COUNT(*)만 NULL 포함 전체 행을 센다.
3 문제 3: 카테고리별 요금 합계
3.1 문제 정보
| 항목 | 내용 |
|---|---|
| 출처 | 튜터 생성 |
| 난이도 | Level 1 |
| SQL 유형 | SUM, WHERE, 문자열 리터럴 |
3.2 문제 설명
CREATE TABLE service_fee (
fee_id INT PRIMARY KEY,
category VARCHAR(30),
fee INT
);
INSERT INTO service_fee VALUES
(1, 'data', 5000),
(2, 'infra', 8000),
(3, 'data', 12000),
(4, 'data', 3000),
(5, 'security', 9000),
(6, 'data', 7000);category가 'data'인 항목의 총 요금을 total_fee로 조회하라.
기대 결과:
| total_fee |
|---|
| 27000 |
3.3 최종 풀이
3.4 Tips
- 핵심 개념:
SUM()집계, 문자열 리터럴 표기 - 함정 1: WHERE 조건이 문제에서 요구하는 필터와 정확히 일치해야 한다.
- 함정 2: 문자열 리터럴은 작은따옴표가 SQL 표준이다. 큰따옴표는 MySQL에서만 동작하며, PostgreSQL·Oracle에서는 식별자(컬럼명·테이블명)로 해석된다.
4 문제 4: 미완료 프로젝트 인원 집계
4.1 문제 정보
| 항목 | 내용 |
|---|---|
| 출처 | 튜터 생성 (앵커: Programmers “나이 정보가 없는 회원 수 구하기” Lv.1, ~88%) |
| 난이도 | Level 1 |
| SQL 유형 | COUNT, IS NULL, WHERE |
4.2 문제 설명
CREATE TABLE project_assignments (
assignment_id INT PRIMARY KEY,
employee_name VARCHAR(50),
department VARCHAR(30),
completion_date DATE
);
INSERT INTO project_assignments VALUES
(1, 'Kim Junho', '개발팀', '2024-02-15'),
(2, 'Lee Soobin', '개발팀', NULL),
(3, 'Park Minjun', '디자인팀', NULL),
(4, 'Choi Yuna', '개발팀', '2024-03-01'),
(5, 'Jung Hana', '개발팀', NULL),
(6, 'Yoon Taeil', '디자인팀', '2024-01-20');개발팀 소속 직원 중 completion_date가 기록되지 않은(아직 미완료) 직원의 수를 incomplete_count로 조회하라.
기대 결과:
| incomplete_count |
|---|
| 2 |
4.3 최종 풀이
SELECT COUNT(*) AS incomplete_count
FROM project_assignments
WHERE department = '개발팀'
AND completion_date IS NULL;IS NULL: NULL 비교는= NULL이 아니라 반드시IS NULLCOUNT(*): NULL 포함 전체 행 카운트 (IS NULL로 이미 필터됐으므로 무관)
4.4 Tips
- 핵심 개념:
IS NULL/IS NOT NULL—= NULL은 항상 FALSE 반환 - 함정:
completion_date = NULL→ 결과 0건. SQL에서 NULL은 값이 아니라 “알 수 없음” - 팁:
COUNT(컬럼)은 NULL 제외,COUNT(*)는 전체 행 — WHERE IS NULL 후 COUNT(*)가 직관적이다.
5 문제 5: 신규 입사자 연봉 범위 조회
5.1 문제 정보
| 항목 | 내용 |
|---|---|
| 출처 | 튜터 생성 (앵커: Programmers “가장 비싼 상품 구하기” Lv.1, ~88%) |
| 난이도 | Level 1 |
| SQL 유형 | MAX, MIN, WHERE 날짜 조건 |
5.2 문제 설명
CREATE TABLE employees (
employee_id INT PRIMARY KEY,
name VARCHAR(30),
department VARCHAR(30),
salary INT,
join_date DATE
);
INSERT INTO employees VALUES
(1, 'Kim', '개발팀', 5500, '2022-06-15'),
(2, 'Lee', '개발팀', 7000, '2023-03-01'),
(3, 'Park', '마케팅', 4800, '2023-07-20'),
(4, 'Choi', '개발팀', 8500, '2022-11-10'),
(5, 'Jung', '마케팅', 6200, '2024-01-05'),
(6, 'Yoon', '개발팀', 5800, '2023-09-15');2023-01-01 이후(당일 포함) 입사한 직원 중 가장 높은 연봉을 max_salary, 가장 낮은 연봉을 min_salary로 조회하라.
기대 결과:
| max_salary | min_salary |
|---|---|
| 7000 | 4800 |
5.3 최종 풀이
SELECT MAX(salary) AS max_salary, MIN(salary) AS min_salary
FROM employees
WHERE join_date >= '2023-01-01';MAX()/MIN(): WHERE 필터 후 남은 행에서 최댓값/최솟값- 두 집계를 SELECT에 동시에 써서 1행으로 반환
5.4 Tips
- 핵심 개념:
MAX(컬럼),MIN(컬럼), GROUP BY 없으면 전체가 1행으로 반환 - 팁:
SELECT MAX(col), MIN(col), AVG(col)처럼 여러 집계 함수를 한 쿼리에 조합 가능
6 문제 6: 조건에 맞는 상품 통계 조회
6.1 문제 정보
| 항목 | 내용 |
|---|---|
| 출처 | 튜터 생성 (앵커: Programmers “평균 일일 대여 요금 구하기” Lv.1, 정답률 ~80%) |
| 난이도 | Level 1 |
| SQL 유형 | COUNT, AVG, ROUND, WHERE, BETWEEN |
6.2 문제 설명
CREATE TABLE products (
product_id INT PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
category VARCHAR(50) NOT NULL,
price INT NOT NULL,
stock_quantity INT NOT NULL
);
INSERT INTO products VALUES
(1, '면 티셔츠', '의류', 15000, 30),
(2, '청바지', '의류', 45000, 10),
(3, '반팔 셔츠', '의류', 22000, 5),
(4, '무선 이어폰', '전자기기', 19000, 20),
(5, '캐주얼 팬츠', '의류', 30000, 0),
(6, '가디건', '의류', 10000, 8);카테고리가 “의류”이고 가격이 10,000원 이상 30,000원 이하이며 재고가 있는 상품의 수(product_count)와 평균 가격(avg_price, 소수점 첫째 자리 반올림)을 조회하라.
기대 결과:
| product_count | avg_price |
|---|---|
| 3 | 15667 |
6.3 최종 풀이
SELECT
COUNT(*) AS product_count,
ROUND(AVG(price)) AS avg_price
FROM products
WHERE category = '의류'
AND stock_quantity > 0
AND price BETWEEN 10000 AND 30000;BETWEEN 10000 AND 30000: 양 끝 경계값(10000, 30000) 포함stock_quantity > 0: 재고 0 제외.IS NOT NULL은 NOT NULL 컬럼에 항상 TRUE라 무의미ROUND(AVG(price)): 두 번째 인자 생략 시 기본값 0 (정수 반올림)
6.4 Tips
- 핵심 개념:
COUNT(*)vsCOUNT(컬럼),ROUND(x, 0) = ROUND(x),BETWEEN양끝 포함 - 함정 1:
stock_quantity IS NOT NULL→ NOT NULL 컬럼에 항상 TRUE, 재고 0 미제외 - 함정 2:
ROUND(AVG(price), 1)→ 소수점 1자리까지 남음 (15666.7). 정수화는 인자 0 또는 생략 - 팁: BETWEEN 앞에 반드시 컬럼명이 온다.
BETWEEN 10000 AND 30000(컬럼 없음)은 문법 오류
7 문제 7: 이벤트 기간 식품 주문 집계
7.1 문제 정보
| 항목 | 내용 |
|---|---|
| 출처 | 튜터 생성 (앵커: Programmers “조건에 맞는 회원 수 구하기” Lv.1, 정답률 ~79%) |
| 난이도 | Level 1 |
| SQL 유형 | COUNT, SUM, WHERE, 날짜 경계값 |
7.2 문제 설명
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
product_name VARCHAR(100),
category VARCHAR(50),
price INT,
ordered_at DATE
);
INSERT INTO orders VALUES
(1, 101, '유기농 사과즙', '식품', 15000, '2024-03-01'),
(2, 102, '노트북', '전자기기', 1200000, '2024-03-02'),
(3, 103, '유기농 녹차', '식품', 8000, '2024-03-05'),
(4, 101, '키보드', '전자기기', 80000, '2024-02-28'),
(5, 104, '유기농 올리브유', '식품', 22000, '2024-03-10'),
(6, 105, '마우스', '전자기기', 45000, '2024-03-15');2024년 3월 1일 이후(해당 날짜 포함) 접수된 ‘식품’ 카테고리 주문의 총 건수(order_count)와 결제 금액 합계(total_price)를 조회하라.
기대 결과:
| order_count | total_price |
|---|---|
| 3 | 45000 |
7.3 최종 풀이
SELECT COUNT(*) AS order_count,
SUM(price) AS total_price
FROM orders
WHERE ordered_at >= '2024-03-01'
AND category = '식품';>=: “이후(해당 날짜 포함)” = 경계값 포함 →>사용 시 3월 1일 주문 1건 누락COUNT(*): 주문 건수(행 수) 기준 —COUNT(price)는 price가 NULL이면 제외SUM(price): NULL 값은 자동 무시하고 합산
7.4 Tips
- 핵심 개념:
COUNT(*)vsCOUNT(컬럼),SUM()NULL 자동 무시 - 함정: “이후” / “부터” =
>=(경계 포함).>쓰면 시작일 데이터가 빠짐 - 팁: “주문 건수”는 행의 존재를 세는 것이므로
COUNT(*)사용이 명시적이다
8 문제 8: 이메일 등록 회원 거주 도시 조회
8.1 문제 정보
| 항목 | 내용 |
|---|---|
| 출처 | 튜터 생성 (앵커: Programmers “중복 제거하기” Lv.1, 정답률 ~80%) |
| 난이도 | Level 1 |
| SQL 유형 | DISTINCT, IS NOT NULL, ORDER BY |
8.2 문제 설명
CREATE TABLE members (
member_id INT PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(100), -- 미등록 시 NULL
city VARCHAR(50),
signup_date DATE
);
INSERT INTO members VALUES
(1, '김민준', 'minjun@email.com', '서울', '2023-01-15'),
(2, '이서연', NULL, '부산', '2023-02-20'),
(3, '박지호', 'jiho@email.com', '서울', '2023-03-05'),
(4, '최유나', 'yuna@email.com', '대전', '2023-04-10'),
(5, '정하은', NULL, '서울', '2023-05-22'),
(6, '강도윤', 'doyun@email.com', '부산', '2023-06-30');이메일이 등록된 회원들의 거주 도시를 중복 없이, 도시명 오름차순으로 조회하라.
기대 결과:
| city |
|---|
| 대전 |
| 부산 |
| 서울 |
8.3 최종 풀이
IS NOT NULL: NULL 비교는=연산자 불가.WHERE email = NULL은 항상 falseDISTINCT city: 중복 도시를 제거한 유일값 반환 — 함수가 아니라 SELECT 절 키워드ORDER BY city ASC: 오름차순 정렬 (ASC는 기본값이나 명시하면 의도가 명확)
8.4 Tips
- 핵심 개념:
IS NOT NULL(NULL 비교),DISTINCT(중복 제거) - 함정 1:
WHERE email = NULL→ 결과 0건. NULL은 어떤 값과=비교해도 NULL(unknown) 반환 - 함정 2:
SELECT DISTINCT(city)→ MySQL에서는 동작하나 함수처럼 보여 오해 소지.SELECT DISTINCT city가 표준 - 팁:
DISTINCT는 SELECT 전체에 적용된다.SELECT DISTINCT city, name은 (city, name) 조합 기준 중복 제거