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 강좌 / UPDATE·DELETE를 실행하기 전 대상 행 확인하기

MariaDB 강좌 / UPDATE·DELETE를 실행하기 전 대상 행 확인하기

UPDATE·DELETE 전에 기본키와 현재값으로 대상 행을 확인하고, InnoDB 트랜잭션에서 수정·삭제 결과를 검증한 뒤 취소합니다. 영향받은 행 수와 ROLLBACK의 적용 한계도 설명합니다.

MariaDB 강좌 / COUNT·SUM·AVG·MIN·MAX로 집계하기

MariaDB 강좌 / COUNT·SUM·AVG·MIN·MAX로 집계하기

COUNT·SUM·AVG·MIN·MAX의 집계 대상과 단위를 상품 재고로 비교합니다. NULL·0·빈 결과의 차이, 행별 계산 후 합계, 최솟값과 해당 행을 혼동하지 않는 기준을 설명합니다.

MariaDB 강좌 / 조회 종합 실습: 월별 매출·고객별 구매·미판매 상품

MariaDB 강좌 / 조회 종합 실습: 월별 매출·고객별 구매·미판매 상품

월별 paid 매출, 미구매 포함 고객별 구매 금액, 미판매 상품 조회를 종합 실습합니다. 주문·상세 단위와 취소 정책을 정하고 세 결과의 전체 금액을 교차 검증합니다.

MariaDB 강좌 / ALTER TABLE로 구조 변경하기: 열·제약 조건·변경 전 점검

MariaDB 강좌 / ALTER TABLE로 구조 변경하기: 열·제약 조건·변경 전 점검

ALTER TABLE을 새 코드 열 추가·기존 행 채우기·제약 적용으로 나누어 실습합니다. NULL·중복 사전 검사, MODIFY 속성 보존, 실제 실패 입력과 잠금·복구 계획을 설명합니다.

MariaDB / 연산자 / 논리 연산자

MariaDB / 연산자 / 논리 연산자

MariaDB의 논리 연산자에 대하여 알아보겠습니다. 예제로 사용하는 테이블은 아래의 데이터를 가진 T_2이라는 테이블입니다. 각 열의 데이터 형식은 다음과 같습니다. C_1 : 정수 C_2 : 문자 +----+------+------+ | ID | C_1 | C_2 | +----+------+------+ | 1 | 1 | A | | 2 | ...

MariaDB 강좌 / NULL·기본값·NOT NULL·CHECK로 입력 조건 정하기

MariaDB 강좌 / NULL·기본값·NOT NULL·CHECK로 입력 조건 정하기

NULL·빈 문자열·0·입력 생략을 구분하고 DEFAULT·NOT NULL·CHECK의 역할을 실습합니다. nullable 열의 CHECK 예외, 실패 입력, 제약 이름과 설정 복원 방법을 설명합니다.

MariaDB 강좌 / 테이블 관계 설계하기: 일대다·다대다·외래키

MariaDB 강좌 / 테이블 관계 설계하기: 일대다·다대다·외래키

고객·상품·주문·상세 네 테이블로 일대다와 다대다 관계를 설계합니다. 복합키·주문 당시 단가·외래키 실패 입력과 삭제 제한을 실행하고 업무상 삭제 정책을 구분합니다.

MariaDB 강좌 / INNER JOIN으로 서로 연결된 데이터 조회하기

MariaDB 강좌 / INNER JOIN으로 서로 연결된 데이터 조회하기

고객과 주문을 INNER JOIN으로 연결하고 결과 한 행의 의미를 확인합니다. ON과 WHERE, 테이블 별칭, 일대다로 늘어나는 행과 조건 없는 곱집합을 비교합니다.

MariaDB 강좌 / 윈도 함수로 순번과 순위 계산하기

MariaDB 강좌 / 윈도 함수로 순번과 순위 계산하기

고객별 금액의 ROW_NUMBER·RANK·DENSE_RANK를 비교하고 지역별 순위와 바깥 조회의 상위 N개 필터를 실습합니다. 공동 순위와 행 개수 제한의 차이를 결과로 확인합니다.

MariaDB 강좌 / WHERE로 조건 지정하기: 비교·AND·OR·IN·BETWEEN·LIKE

MariaDB 강좌 / WHERE로 조건 지정하기: 비교·AND·OR·IN·BETWEEN·LIKE

상품 가격·분류·재고·이름으로 WHERE 조건을 실습합니다. AND·OR 괄호 차이, IN 목록, BETWEEN 경계, LIKE 와일드카드와 실제 퍼센트 검색을 예상 행 번호로 확인합니다.