MySQL에서 UNION 대신 CASE 문을 사용해야 하는 이유
MySQL에서 여러 조건의 결과를 하나의 순서로 합쳐서 조회하고 싶을 때 많은 개발자가 UNION을 떠올립니다. 하지만 UNION은 내부적으로 결과를 병합하면서 원래의 정렬 순서를 보장하지 않기 때문에, 의도한 순서대로 데이터가 출력되지 않는 문제가 발생할 수 있습니다.
이런 경우 가장 좋은 해결책은 CASE 문과 ORDER BY를 함께 사용하는 것입니다. UNION을 쓰지 않고도 원하는 조회 순서를 깔끔하게 유지할 수 있습니다.
아래에서 실제 예제를 통해 단계별로 살펴보겠습니다.
1단계: 테이블 생성하기
먼저 배송 날짜(ShippingDate)를 저장할 테이블을 생성합니다.
mysql> create table DemoTable
(
Id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
ShippingDate datetime
);
Query OK, 0 rows affected (0.63 sec)
2단계: 샘플 데이터 삽입하기
INSERT 명령어를 사용해 몇 개의 레코드를 추가합니다.
mysql> insert into DemoTable(ShippingDate) values('2019-04-21');
Query OK, 1 row affected (0.17 sec)
mysql> insert into DemoTable(ShippingDate) values('2019-01-01');
Query OK, 1 row affected (0.13 sec)
mysql> insert into DemoTable(ShippingDate) values('2019-05-11');
Query OK, 1 row affected (0.16 sec)
mysql> insert into DemoTable(ShippingDate) values('2018-12-31');
Query OK, 1 row affected (0.18 sec)
mysql> insert into DemoTable(ShippingDate) values('2019-02-18');
Query OK, 1 row affected (0.19 sec)3단계: 전체 데이터 확인하기
SELECT 문으로 테이블의 모든 레코드를 조회해 보겠습니다.
mysql> select *from DemoTable;
실행 결과는 다음과 같습니다.
+----+---------------------+
| Id | ShippingDate |
+----+---------------------+
| 1 | 2019-04-21 00:00:00 |
| 2 | 2019-01-01 00:00:00 |
| 3 | 2019-05-11 00:00:00 |
| 4 | 2018-12-31 00:00:00 |
| 5 | 2019-02-18 00:00:00 |
+----+---------------------+
5 rows in set (0.00 sec)
CASE 문으로 조회 순서 유지하기
이제 핵심인 쿼리입니다. ORDER BY 절에 CASE 문을 적용하면, 과거 날짜와 현재 이후의 날짜를 구분하여 원하는 순서대로 정렬할 수 있습니다.
mysql> select *from DemoTable
ORDER
BY CASE WHEN ShippingDate < CURDATE() THEN ShippingDate ELSE CURDATE() END DESC,
ShippingDate ASC;
위 쿼리의 동작 방식은 다음과 같습니다.
- CASE WHEN ShippingDate < CURDATE(): 오늘보다 이전 날짜라면 해당 날짜 값을 그대로 사용합니다.
- ELSE CURDATE(): 오늘 이후의 날짜는 모두 오늘 날짜(CURDATE())로 통일합니다.
- 첫 번째 정렬 기준 DESC: 통합된 값 기준으로 내림차순 정렬하여 최신 날짜가 앞에 오도록 합니다.
- 두 번째 정렬 기준 ShippingDate ASC: 같은 그룹 내에서는 날짜 오름차순으로 정렬합니다.
실행 결과는 다음과 같습니다.
+----+---------------------+
| Id | ShippingDate |
+----+---------------------+
| 3 | 2019-05-11 00:00:00 |
| 1 | 2019-04-21 00:00:00 |
| 5 | 2019-02-18 00:00:00 |
| 2 | 2019-01-01 00:00:00 |
| 4 | 2018-12-31 00:00:00 |
+----+---------------------+
5 rows in set (0.00 sec)
정리
UNION을 사용하면 각 SELECT 결과의 순서가 병합 과정에서 무시될 수 있습니다. 반면 ORDER BY + CASE 문을 활용하면 단일 쿼리 안에서 조건별 우선순위를 명확하게 제어할 수 있어, 성능과 가독성 면에서 모두 유리합니다. 조건에 따른 커스텀 정렬이 필요하다면 UNION 대신 CASE 문을 적극적으로 활용해 보세요.