AD JB Toolbox 01

MariaDB 강좌 / CASE로 조건별 값과 집계 만들기

CASE는 조건에 따라 하나의 값을 선택하는 SQL 표현식입니다. 상품 상태를 표시하거나 집계 함수 안에서 특정 조건의 값만 선택할 수 있으며, 조건의 순서·ELSE·NULL 처리에 따라 결과가 달라집니다.

CASE 표현식과 절차 제어를 구분하기

이 글의 CASE는 SELECT의 결과값 하나를 만드는 표현식입니다. 여러 SQL 문을 실행하는 저장 프로그램의 CASE 문과 구분합니다. 재고가 0인지·10보다 적은지 같은 조건을 평가하고 처음 참인 조건의 결과를 선택하므로 겹치는 조건의 순서가 중요합니다. 조건식 자체가 맞아도 집계 단위를 잘못 정하면 결과가 달라집니다. COUNT·SUM·AVG·MIN·MAX로 집계하기의 COUNT·SUM 기준과 조회 종합 실습: 월별 매출·고객별 구매·미판매 상품의 보고서 검증을 함께 확인하세요.

형태 사용 상황 예
CASE 값 WHEN 값 THEN 결과 동등한 코드 매핑 분류 '문구'를 표시 이름으로
CASE WHEN 조건 THEN 결과 범위·복합 조건 stock < 10
ELSE 결과 어느 조건에도 해당하지 않음 판매 가능
END 표현식 끝 뒤에 AS 별칭 지정

재고가 서로 다른 상품으로 준비하기

학습용 MariaDB 서버의 shopcourse에 course_user로 접속합니다. 명령줄 클라이언트와 UTF-8 SQL 파일 실행 방법대로 코드를 UTF-8 파일에 저장하고 SOURCE C:/mariadb-lab/lesson.sql;처럼 실제 파일 경로로 실행할 수 있습니다. SQL 문은 운영체제 터미널이 아닌 MariaDB 연결 안에서 실행합니다.

먼저 SELECT VERSION(), DATABASE();와 SHOW TABLES;로 대상 서버·DB·이름 중복을 확인합니다. 아래 products_24_lab는 이 글의 독립된 연습용 이름입니다. 이미 존재하면 정의와 행을 확인하고, 보관할 자료가 없는 이 글의 실습 테이블임이 확실할 때만 마지막 절의 정리 순서로 지운 뒤 다시 만듭니다. 기존 강좌의 동명 없는 테이블이나 운영 데이터는 삭제하지 않습니다.

USE shopcourse;
CREATE TABLE products_24_lab (
  product_id INT NOT NULL AUTO_INCREMENT,
  product_name VARCHAR(100) NOT NULL,
  category VARCHAR(30) NOT NULL,
  price DECIMAL(10,2) NOT NULL,
  stock INT NOT NULL DEFAULT 0,
  note VARCHAR(100) NULL DEFAULT NULL,
  PRIMARY KEY (product_id),
  CONSTRAINT ck_p24_price CHECK (price >= 0),
  CONSTRAINT ck_p24_stock CHECK (stock >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO products_24_lab (product_id,product_name,category,price,stock,note) VALUES (1, '노트', '문구', 3500.00, 20, NULL),
  (2, '볼펜', '문구', 1500.00, 0, ''),
  (3, '머그컵', '생활', 8000.00, 12, '선물 포장'),
  (4, '스탠드', '생활', 25000.00, 5, NULL),
  (5, '파일', '문구', 1500.00, 50, ''),
  (6, '케이블', '전자', 8000.00, 0, '호환 확인');

재고 0인 상품 두 개, 1~9개인 상품 한 개, 10개 이상인 상품 세 개입니다. 이 구분은 학습용 정책이므로 실제 판매 가능 상태에 예약·입고 예정·판매 중지 같은 다른 조건이 있다면 함께 설계해야 합니다.

좁은 조건부터 평가해 상태값 표시하기

SELECT product_id,product_name,stock,
 CASE WHEN stock=0 THEN '품절'
      WHEN stock<10 THEN '재고 적음'
      ELSE '판매 가능' END AS stock_label
FROM products_24_lab ORDER BY product_id;

번호 2·6번은 품절, 4번은 재고 적음, 1·3·5번은 판매 가능입니다. stock < 10을 먼저 적으면 0도 그 조건에 해당하므로 품절 조건이 선택되지 않습니다. 조건 하나의 순서를 바꿔 결과를 비교한 다음 원래 순서로 되돌려 보세요.

ELSE를 생략했는데 어느 WHEN에도 해당하지 않으면 결과가 NULL입니다. 화면에서 비어 보이는 이유가 원본 NULL인지 CASE의 미정의 분기인지 구분해야 합니다. CASE 연산자의 선택 순서와 ELSE를 확인할 수 있습니다.

SUM과 COUNT 안에서 조건별 개수 구하기

SELECT SUM(CASE WHEN stock=0 THEN 1 ELSE 0 END) AS out_of_stock,
 COUNT(CASE WHEN stock=0 THEN 1 END) AS also_out_of_stock,
 COUNT(CASE WHEN stock=0 THEN 1 ELSE 0 END) AS all_non_null,
 SUM(CASE WHEN category='문구' THEN price*stock ELSE 0 END) AS stationery_value
FROM products_24_lab;
표현 결과 이유
SUM(CASE ... THEN 1 ELSE 0 END) 2 품절 행에 1을 더함
COUNT(CASE ... THEN 1 END) 2 품절 이외에는 NULL이라 제외
COUNT(CASE ... THEN 1 ELSE 0 END) 6 0도 NULL이 아닌 값이라 포함
문구 재고 금액 145000.00 문구 행의 가격×재고만 합산

COUNT가 숫자 1만 센다고 오해하면 ELSE 0을 넣은 결과를 잘못 해석합니다. COUNT(표현식)는 NULL이 아닌 표현식 값을 세며 0도 포함합니다. 조건별 집계에서는 SUM의 1·0 방식 또는 COUNT의 1·NULL 방식을 의도에 맞게 선택합니다.

결과 타입과 NULL 정책을 함께 정하기

THEN에는 숫자, ELSE에는 임의의 문자열을 섞으면 결과 타입 변환 때문에 후속 계산이나 정렬을 이해하기 어려워질 수 있습니다. 계산용 금액은 숫자로 유지하고 상태 문구는 별도 열로 반환하는 편이 명확합니다. 가격이 NULL일 때 0원으로 처리할지도 업무에서 결정해야 합니다.

SELECT category,
 SUM(CASE WHEN stock>0 THEN 1 ELSE 0 END) AS available_products
FROM products_24_lab GROUP BY category ORDER BY category;

분류별 재고 보유 상품 수는 문구 2개·생활 2개·전자 0개입니다. WHERE stock>0을 먼저 적용하면 전자 그룹 자체가 사라지지만 CASE로 합산하면 전자 그룹에 0을 표시할 수 있습니다. 어떤 결과 형태가 필요한지에 따라 두 방식을 선택합니다.

집계 전 원본 행과 분기를 확인하기

합계만 한 번에 확인하지 말고 먼저 기본키·재고·CASE 결과를 출력해 각 행이 어느 분기로 갔는지 살펴봅니다. 조건에 =와 >를 혼동했는지, AND·OR 괄호가 맞는지, ELSE를 빠뜨리지 않았는지도 확인합니다. CASE는 조회 결과를 만들며 원본 stock을 수정하지 않습니다.

반복하기 전 현재 DB와 실제 정의·행을 확인하고 필요한 자료를 백업합니다. 보관할 데이터가 없는 이 글의 전용 실습 객체만 아래 순서로 정리합니다. 외래키가 있으면 자식부터 지웁니다. DROP TABLE은 구조와 데이터를 모두 없애며 일반적인 ROLLBACK으로 복원되지 않으므로 취소 가능한 DML 실습과 분리합니다.

DROP TABLE shopcourse.products_24_lab;
같은 카테고리의 다른 글
MariaDB 강좌 / mariadb-dump로 데이터베이스 백업하기

MariaDB 강좌 / mariadb-dump로 데이터베이스 백업하기

별도 주문 실습 DB를 준비해 mariadb-dump로 새 SQL 백업 파일을 만듭니다. 종료 코드·해시·문자 인코딩, InnoDB 스냅샷과 동시 DDL의 한계, 객체·권한·별도 복원 검증 기준을 설명합니다.

MariaDB 강좌 / CREATE TABLE로 테이블 구조 정의하기

MariaDB 강좌 / CREATE TABLE로 테이블 구조 정의하기

상품 테이블을 예로 열·타입·기본값·기본키·저장 엔진을 정의하고 실제 생성 결과를 확인합니다. 기존 테이블 처리, IF NOT EXISTS의 한계와 안전한 반복 실습 방법도 설명합니다.

MariaDB 강좌 / Ubuntu에 MariaDB 설치하고 서버 실행하기

MariaDB 강좌 / Ubuntu에 MariaDB 설치하고 서버 실행하기

Ubuntu APT 설치 후 서버 실행·자동 시작·관리자 소켓 인증을 확인합니다. 로컬 TCP 학습 계정을 만들고 패키지 버전, 인증 오류와 서비스 로그를 확인하는 절차를 설명합니다.

MariaDB / 샘플 데이터베이스 employees 설치하는 방법

MariaDB / 샘플 데이터베이스 employees 설치하는 방법

데이터베이스를 다루는 공부를 할 때 데이터가 들어있는 데이터베이스가 있으면 좋습니다. 데이터베이스를 직접 만드는 방법도 있지만, 공개된 샘플 데이터베이스를 이용하면 편합니다. 예를 들어 SQL Server라면 AdventureWorks라는 샘플 데이터베이스를 마이크로소프트에서 제공합니다. MariaDB라면 employees를 사용하면 됩니다.

MariaDB 강좌 / 로컬·원격 접속과 연결 오류 해결하기

MariaDB 강좌 / 로컬·원격 접속과 연결 오류 해결하기

로컬 TCP 연결을 명시하고 서버 정보·현재 계정·실제 테이블 권한을 확인합니다. 연결 거절·인증·DB 오류를 나누어 진단하고 원격 수신 주소·계정·TLS의 적용 조건을 설명합니다.

MariaDB 강좌 / 서브쿼리·EXISTS·NOT EXISTS로 조건 표현하기

MariaDB 강좌 / 서브쿼리·EXISTS·NOT EXISTS로 조건 표현하기

평균값 서브쿼리와 EXISTS·NOT EXISTS를 상품·고객·주문으로 실습합니다. 한 값의 반환 조건, 상관 키 누락, paid 주문 부재의 정의와 NOT IN의 NULL 함정을 설명합니다.

MariaDB / Query / LEFT JOIN, RIGHT JOIN, INNER JOIN

MariaDB / Query / LEFT JOIN, RIGHT JOIN, INNER JOIN

SQL의 JOIN은 여러 테이블을 한 번에 나타낼 때 사용합니다. 대표적인 JOIN 방식은 LEFT JOIN, RIGHT JOIN, INNER JOIN이 있습니다. 다음은 세 가지 JOIN의 차이를 알아보기 위한 간단한 예제 테이블입니다.

MariaDB 강좌 / 첫 실습: 상품 테이블을 만들고 데이터를 넣어 조회하기

MariaDB 강좌 / 첫 실습: 상품 테이블을 만들고 데이터를 넣어 조회하기

상품 세 건을 저장하는 전체 SQL로 테이블 생성·입력·조회 과정을 실습합니다. 구조와 행 수, 가격·재고 조건의 예상 결과를 확인하고 반복 입력 오류와 실습 테이블 초기화 범위를 구분합니다.

MariaDB 강좌 / 인덱스 만들기: 단일·복합 인덱스와 열 순서

MariaDB 강좌 / 인덱스 만들기: 단일·복합 인덱스와 열 순서

기존 키를 조회한 뒤 고객·날짜 복합 인덱스를 만들고 같은 조회 결과를 확인합니다. 열 순서·범위·커버링, 쓰기 비용·중복 키·외래키 지원 인덱스의 주의점을 설명합니다.

MariaDB 강좌 / 여러 테이블 JOIN하기: 중복 행과 집계 오류 확인

MariaDB 강좌 / 여러 테이블 JOIN하기: 중복 행과 집계 오류 확인

고객·주문·상세·상품을 JOIN하고 행 증가에 따른 배송비 중복 합산을 확인합니다. COUNT DISTINCT와 SUM DISTINCT의 차이, 주문별 선집계로 올바른 금액을 얻는 방법을 설명합니다.