[SQL] 3465. Find Products with Valid Serial Numbers

양승우·2025년 5월 7일

코드카타

목록 보기
57/58

문제

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의 도움에 따르면 아래와 같이 정리할 수 있겠다.

항목LIKEREGEXP
기능간단한 패턴 검색정규표현식 기반의 복잡한 검색 가능
와일드카드% (모든 문자), _ (한 문자). (한 문자), *, +, ?, `, [], ()` 등 다양
예시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]|$) → 뒤에 숫자가 없거나, 문자열 끝
profile
어제보다 오늘 더

0개의 댓글