COALESCE는 목록에서 NULL이 아닌 첫 번째 값을 반환해요. SQL에서 누락된 값을 대체값으로 바꾸는 방법이죠. 예제는 PostgreSQL, MySQL, SQLite, SQL Server에서 동작해요.
COALESCE 사용법
COALESCE에는 값을 몇 개든 넘길 수 있어요. 왼쪽부터 오른쪽으로 확인해서 NULL이 아닌 첫 번째 값을 반환하고, 모두 NULL이면 NULL을 반환해요:
COALESCE(value1, value2, ...)
SELECT COALESCE(NULL, 'second', 'third');
-- Output: second
SELECT COALESCE(NULL, NULL);
-- Output: NULL
실제 쿼리에서는 보통 컬럼을 넣고, 마지막 수단으로 끝에 리터럴을 둬요:
-- Input: users
-- id | name | nickname
-- ---+--------------+---------
-- 1 | Maria Garcia | Mia
-- 2 | Tom Becker | NULL
-- 3 | Priya Shah | P
SELECT id, name, COALESCE(nickname, name) AS display_name
FROM users;
-- Output:
-- id | name | display_name
-- ---+--------------+-------------
-- 1 | Maria Garcia | Mia
-- 2 | Tom Becker | Tom Becker
-- 3 | Priya Shah | P
알아둘 규칙
- NULL이 아닌 첫 번째 값에서 멈춰요. 값을 찾으면 뒤의 인수는 평가하지 않아요. 가장 자주 채워지는 값을 앞에 두세요.
- 모든 인수의 타입이 호환되어야 해요. 숫자와 텍스트를 섞으면 PostgreSQL과 SQL Server에서 실패하니 먼저 캐스팅하세요:
-- Input: products
-- name | stock
-- -------------+------
-- Desk Lamp | 12
-- Office Chair | NULL
SELECT name, COALESCE(stock, 'N/A') AS stock FROM products;
-- PostgreSQL: ERROR: invalid input syntax for type integer: "N/A"
-- SQL Server: Conversion failed when converting the varchar value 'N/A' to data type int.
-- (in MySQL, cast with CAST(stock AS CHAR))
SELECT name, COALESCE(CAST(stock AS VARCHAR(10)), 'N/A') AS stock FROM products;
-- Output:
-- name | stock
-- -------------+------
-- Desk Lamp | 12
-- Office Chair | N/A
-
빈 문자열은 NULL이 아니에요. COALESCE는
''를 그대로 통과시켜요. 빈 문자열도 누락으로 처리하려면 컬럼을NULLIF(column, '')로 감싸세요:
SELECT COALESCE('', 'No name');
-- Output: '' (an empty string)
SELECT COALESCE(NULLIF('', ''), 'No name');
-- Output: No name
대체 문법
인수 2개짜리 단축 함수도 보게 될 거예요. MySQL과 SQLite의 IFNULL, SQL Server의 ISNULL이에요:
SELECT IFNULL(NULL, 'fallback');
-- Output: fallback
COALESCE를 쓰는 게 좋아요. 인수를 몇 개든 받을 수 있고, SQL Server의 ISNULL은 결과에 첫 번째 인수의 타입을 적용해서 대체값이 잘릴 수 있거든요:
-- SQL Server
DECLARE @code VARCHAR(2) = NULL;
SELECT ISNULL(@code, 'none') AS with_isnull, COALESCE(@code, 'none') AS with_coalesce;
-- Output:
-- with_isnull | with_coalesce
-- ------------+--------------
-- no | none
CASE 표현식으로도 같은 일을 할 수 있지만 더 길어져요. COALESCE(nickname, name)은 CASE WHEN nickname IS NOT NULL THEN nickname ELSE name END의 축약형이에요. 더 강력한 기능이 필요할 때는 SQL CASE 문 가이드를 참고하세요.
COALESCE는 언제 사용해야 할까요?
NULL 때문에 결과가 틀리거나, 보기 안 좋거나, 비어 버릴 때마다 COALESCE를 쓰세요. 대부분의 용도는 다음 4가지 중 하나예요.
다른 컬럼으로 대체하기
원하는 값이 여러 컬럼 중 하나에 있을 때 COALESCE는 채워진 첫 번째 값을 골라요. 닉네임 또는 전체 이름, 휴대전화 또는 유선전화, 배송지 또는 청구지 주소처럼요.
모든 값이 없을 때 기본값 사용하기
목록 끝에 리터럴을 두면 결과가 절대 NULL이 되지 않아요. 빈칸보다 “Address Unknown”이나 0.00이 더 읽기 좋은 보고서나 화면에 딱 맞아요.
계산된 값으로 빈 곳 채우기
대체값이 꼭 컬럼이나 상수일 필요는 없어요. 다른 컬럼으로 만든 사용자 이름이나 이메일 주소 같은 표현식도 될 수 있어서, 가져온 데이터를 정리할 때 COALESCE가 유용해요.
계산에서 NULL 배제하기
NULL이 포함된 산술 연산은 모두 NULL이 되기 때문에, 할인이나 보너스가 하나만 빠져도 합계 전체가 사라져요. COALESCE(discount, 0)은 누락된 값을 계산에 쓸 수 있는 숫자로 바꿔줘요.
COALESCE 실전 예제
저장된 가격 중 하나 표시하기
상품에는 할인가, 정가가 있거나 (출시 전에는) 둘 다 없을 수 있어요. 순서대로 확인하고 기본값은 0으로 두세요:
-- Input: products
-- product_id | name | sale_price | regular_price
-- -----------+---------------+------------+--------------
-- 1 | Desk Lamp | 19.99 | 24.99
-- 2 | Office Chair | NULL | 149.00
-- 3 | Standing Desk | NULL | NULL
SELECT product_id, name, COALESCE(sale_price, regular_price, 0.00) AS price
FROM products;
-- Output:
-- product_id | name | price
-- -----------+---------------+-------
-- 1 | Desk Lamp | 19.99
-- 2 | Office Chair | 149.00
-- 3 | Standing Desk | 0.00
연락할 최적의 전화번호 고르기
연락처에는 번호가 최대 3개 있어요. 사용 가능한 첫 번째 번호를 보여주고, 없으면 없다고 표시하세요:
-- Input: contacts
-- name | primary_phone | mobile_phone | work_phone
-- -----+---------------+--------------+-----------
-- Ada | 555-0101 | 555-0199 | NULL
-- Bo | NULL | 555-0142 | 555-0177
-- Cy | NULL | NULL | 555-0123
-- Di | NULL | NULL | NULL
SELECT name, COALESCE(primary_phone, mobile_phone, work_phone, 'No phone') AS phone
FROM contacts;
-- Output:
-- name | phone
-- -----+---------
-- Ada | 555-0101
-- Bo | 555-0142
-- Cy | 555-0123
-- Di | No phone
임시 이메일 주소 생성하기
이메일이 등록되지 않은 직원에게는 이름으로 만든 주소를 부여해서, 디렉터리의 모든 행에 값이 있도록 해요:
-- Input: employees
-- employee_id | first_name | last_name | email
-- ------------+------------+-----------+-----------------
-- 1 | Grace | Hopper | ghopper@navy.mil
-- 2 | Alan | Turing | NULL
SELECT
employee_id,
first_name || ' ' || last_name AS full_name,
COALESCE(
email,
LOWER(first_name) || '.' || LOWER(last_name) || '@company.com'
) AS email
FROM employees;
-- Output:
-- employee_id | full_name | email
-- ------------+--------------+------------------------
-- 1 | Grace Hopper | ghopper@navy.mil
-- 2 | Alan Turing | alan.turing@company.com
MySQL과 SQL Server에서는 || 대신 CONCAT()으로 문자열을 연결하세요.
할인이 선택 사항일 때 주문 합계 구하기
COALESCE가 없으면 할인이 없는 줄 하나 때문에 주문 합계 전체가 틀어져요. SUM이 NULL인 줄을 아예 건너뛰기 때문이에요:
-- Input: order_items
-- order_id | product | quantity | unit_price | discount
-- ---------+----------+----------+------------+---------
-- 101 | Keyboard | 1 | 49.00 | 5.00
-- 101 | Mouse | 2 | 19.50 | NULL
-- 102 | Monitor | 1 | 189.00 | NULL
-- 102 | Cable | 3 | 6.00 | 2.00
-- Wrong: lines with a NULL discount drop out of the total
SELECT order_id, SUM(quantity * unit_price - discount) AS total
FROM order_items
GROUP BY order_id
ORDER BY order_id;
-- Output:
-- order_id | total
-- ---------+------
-- 101 | 44.00
-- 102 | 16.00
-- Right: a missing discount counts as 0
SELECT order_id, SUM(quantity * unit_price - COALESCE(discount, 0)) AS total
FROM order_items
GROUP BY order_id
ORDER BY order_id;
-- Output:
-- order_id | total
-- ---------+-------
-- 101 | 83.00
-- 102 | 205.00
COALESCE 관련 추가 자료
이 블로그의 글:
-
MySQL COALESCE: COALESCE와 MySQL의
IFNULL비교 - SQL CASE 문 가이드: NULL 확인을 넘어선 조건 로직
- SQL 같지 않음 연산자 가이드: NULL과의 비교가 절대 일치하지 않는 이유
- SQL GROUP BY 가이드: COALESCE와 자주 함께 쓰이는 집계 함수
- SQL SUBSTRING 가이드: NULL일 수 있는 컬럼에서 텍스트 추출하기
공식 문서:
Beekeeper Studio는 무료 오픈 소스 데이터베이스 GUI예요
지금까지 써 본 SQL 쿼리 & 에디터 도구 중 최고예요. 데이터베이스 관리에 필요한 모든 게 다 있어요. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio는 빠르고 직관적이며 사용하기 쉬워요. 다양한 데이터베이스를 지원하고 Windows, Mac, Linux에서 모두 잘 작동해요.
Beekeeper Studio 사용자 후기
"Beekeeper Studio가 예전 SQL 작업 방식을 완전히 대체했어요. 빠르고 직관적이라 데이터베이스 작업이 다시 즐거워졌어요."
"여러 데이터베이스 GUI를 써봤지만, Beekeeper는 기능과 단순함 사이의 균형이 완벽해요. 그냥 잘 돼요."