3465. Find Products with Valid Serial Numbers
description에 아래 조건에 맞는 시리얼 번호가 있는 경우만 필터링하라
- SN으로 시작한다
- 이어서 4자리 숫자가 등장한다
- 이어서 하이픈(-)이 나오고 그 뒤에 4자리 숫자가 따라온다
description이 반드시 시리얼 번호로 시작해야 하는 것은 아니고, 포함만 하면 된다
결국 이 문제는 단순 LIKE로는 풀 수 없는, 정규표현식을 요하는 문제이다
LIKE에서 사용할 수 있는 와일드카드는 %(n개 문자)와 _(1개 문자)가 있는데,
이 둘은 모두 개수만 의미할 뿐 alpha와 digit을 구분하지 못한다
반면 REGEXP는 [A-Za-z]와 [0-9]를 통해 문자/숫자를 구분하여 지정할 수 있다.
GPT의 도움에 따르면 아래와 같이 정리할 수 있겠다.
| 항목 | LIKE | REGEXP | |
|---|---|---|---|
| 기능 | 간단한 패턴 검색 | 정규표현식 기반의 복잡한 검색 가능 | |
| 와일드카드 | % (모든 문자), _ (한 문자) | . (한 문자), *, +, ?, ` | , [], ()` 등 다양 |
| 예시 | name LIKE 'A%' → A로 시작 | name REGEXP '^A' → A로 시작 | |
| 복잡한 조건 | 거의 불가능 | 가능 (예: 숫자 4자리만, 대문자+숫자 조합 등) | |
| 지원 범위 | 대부분의 DB에서 지원 | MySQL, PostgreSQL 등 일부 DB에서만 지원 (다만 기능 차이 있음) |
우선 문제에서 요구하는 형태를 필터링할 수 있도록 표현식의 기본 틀부터 만들었다
SELECT
*
FROM
products
WHERE
description REGEXP '(SN)[0-9]{4}-[0-9]{4}'
ORDER BY
product_id
;
SN____-____ 형태를 포함하는 케이스를 필터링하는 방식이다
다만, 이는 뒤에 추가로 숫자가 붙는 경우를 제외하지 못한다
문제 조건에서는 하이픈 뒤로 정확히 숫자 4개가 오는 경우만을 찾도록 요구하기에,
아래와 같은 경우를 걸러내야 한다

정규표현식에서는 Lookahead라는 기능을 통해 문자열 뒤에 특정 문자열이 존재하거나/하지 않는 경우를 확인할 수 있다.
이를 ?!으로 사용할 수 있다
해당 문제에서는, 앞선 조건 후방에 (?![0-9])를 작성함으로써, 문자열 뒤에 추가로 숫자가 붙지 않는 경우만을 걸러낼 수있다.
SELECT
*
FROM
products
WHERE
description REGEXP '(SN)[0-9]{4}-[0-9]{4}(?![0-9])'
ORDER BY
product_id
;
그래서 동일한 방법으로 SN으로 시작한다는 조건도 만족시키고 싶었으나...
SELECT
*
FROM
products
WHERE
description REGEXP '(?![A-Za-z])(SN)[0-9]{4}-[0-9]{4}(?![0-9])'
ORDER BY
product_id
;
이처럼 작성하면 그냥 모든 결과가 제외되어 버린다.
GPT에 따르면 MySQL에서 전방 탐색은 부분적으로 지원되나, 후방 탐색은 지원하지 않는다고 한다
결국 (1) 시리얼 번호로 시작되는 경우와 (2) 시리얼 번호가 중간에 포함되는 경우를 모두 입력하고 OR로 묶어주었다
SELECT
*
FROM
products
WHERE
description REGEXP '(^SN)[0-9]{4}-[0-9]{4}(?![0-9])'
OR description REGEXP '( SN)[0-9]{4}-[0-9]{4}(?![0-9])'
ORDER BY
product_id
;
Lookahead를 사용하지 않고 정규표현식 한 줄로도 처리가 가능하다
SELECT
*
FROM
products
WHERE
description REGEXP '(^|[^A-Za-z0-9])SN[0-9]{4}-[0-9]{4}([^0-9]|$)'
ORDER BY
product_id
;
(^|[^A-Za-z0-9]) → 시작이거나, 문자/숫자가 아닌 경우 (앞쪽)SN[0-9]{4}-[0-9]{4} → 찾고자 하는 패턴([^0-9]|$) → 뒤에 숫자가 없거나, 문자열 끝