MySQL 테이블에서 사용되지 않는 최솟값 찾기
MySQL 테이블에 저장된 연속된 숫자 값 사이에서 비어 있는(사용되지 않는) 가장 작은 값을 찾아야 할 때가 있습니다. 이럴 때 LEFT JOIN을 활용하면 간단하게 해결할 수 있습니다. 이번 글에서는 예제를 통해 그 방법을 단계별로 알아보겠습니다.
1. 테이블 생성하기
먼저 예제에 사용할 테이블을 생성합니다.
mysql> create table FindValue
-> (
-> SequenceNumber int
-> );
Query OK, 0 rows affected (0.56 sec)
2. 데이터 삽입하기
INSERT 명령을 사용해 몇 개의 레코드를 삽입합니다. 여기서 112가 빠져 있다는 점에 주목하세요.
mysql> insert into FindValue values(109);
Query OK, 1 row affected (0.14 sec)
mysql> insert into FindValue values(110);
Query OK, 1 row affected (0.15 sec)
mysql> insert into FindValue values(111);
Query OK, 1 row affected (0.13 sec)
mysql> insert into FindValue values(113);
Query OK, 1 row affected (0.13 sec)
mysql> insert into FindValue values(114);
Query OK, 1 row affected (0.17 sec)
3. 전체 레코드 확인하기
SELECT 문으로 테이블의 모든 레코드를 조회해 봅니다.
mysql> select *from FindValue;
실행 결과는 다음과 같습니다.
+----------------+ | SequenceNumber | +----------------+ | 109 | | 110 | | 111 | | 113 | | 114 | +----------------+ 5 rows in set (0.00 sec)
4. 사용되지 않는 최솟값을 찾는 쿼리
다음은 LEFT JOIN을 이용해 시퀀스에서 비어 있는 최솟값을 찾는 쿼리입니다.
mysql> select tbl1.SequenceNumber+1 AS ValueNotUsedInSequenceNumber
-> from FindValue AS tbl1
-> left join FindValue AS tbl2 ON tbl1.SequenceNumber+1 = tbl2.SequenceNumber
-> WHERE tbl2.SequenceNumber IS NULL
-> ORDER BY tbl1.SequenceNumber LIMIT 1;
실행 결과는 다음과 같습니다.
+------------------------------+ | ValueNotUsedInSequenceNumber | +------------------------------+ | 112 | +------------------------------+ 1 row in set (0.00 sec)
쿼리 동작 원리
이 쿼리의 핵심은 동일한 테이블을 두 번 조인하는 셀프 조인(Self Join) 방식입니다. 동작 과정을 정리하면 다음과 같습니다.
- tbl1의 SequenceNumber에 1을 더한 값이 tbl2의 SequenceNumber와 일치하는 행을 찾습니다.
- 일치하는 행이 없다면(
WHERE tbl2.SequenceNumber IS NULL), 해당 숫자의 다음 값은 시퀀스에서 비어 있다는 의미입니다. ORDER BY와LIMIT 1을 사용해 후보 값 중 가장 작은 값 하나만 반환합니다.
위 예제에서는 111 다음 숫자인 112가 비어 있으므로, 쿼리 결과로 112가 반환됩니다. 이 방식은 주문 번호, 일련번호 등 중간에 삭제된 값이나 건너뛴 값을 찾아 재활용해야 하는 상황에서 특히 유용하게 활용할 수 있습니다.