1527. Patients With a Condition
Write a solution to find the patient_id, patient_name, and conditions ofthe patients
who have Type I Diabetes. Type I Diabetes always starts with DIAB1 prefix.
+------------+--------------+--------------+
| patient_id | patient_name | conditions |
+------------+--------------+--------------+
| 1 | Daniel | YFEV COUGH |
| 2 | Alice | |
| 3 | Bob | DIAB100 MYOP |
| 4 | George | ACNE DIAB100 |
| 5 | Alain | DIAB201 |
+------------+--------------+--------------+
+------------+--------------+--------------+
| patient_id | patient_name | conditions |
+------------+--------------+--------------+
| 3 | Bob | DIAB100 MYOP |
| 4 | George | ACNE DIAB100 |
+------------+--------------+--------------+
정규 표현식 (Regular Expression, regexp) 이란?
특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어이다. 정규 표현식은 많은 텍스트 편집기와 프로그래밍 언어에서 문자열의 검색과 치환을 위해 지원하고 있다.
정규 표현식이라는 문구는 일치하는 텍스트가 준수해야 하는 "패턴"을 표현하기 위해 특정한 표준의 텍스트 신택스를 의미하기 위해 사용된다.
MySQL의 주요 정규표현식 패턴
| 패턴 | 설명 |
|---|---|
[abc] | 'a', 'b', 'c' 중 하나를 매칭합니다. |
[a-z] | 소문자 알파벳을 매칭합니다. |
[^a-z] | 소문자 알파벳이 아닌 모든 문자를 매칭합니다. |
[A-Z] | 대문자 알파벳을 매칭합니다. |
[0-9] | 숫자를 매칭합니다. |
| 패턴 | 설명 |
|---|---|
^ | 문자열의 시작을 매칭합니다. |
$ | 문자열의 끝을 매칭합니다. |
^word: "word"로 시작하는 문자열을 매칭합니다.word$: "word"로 끝나는 문자열을 매칭합니다.| 패턴 | 설명 |
|---|---|
* | 0번 이상 반복을 매칭합니다. |
+ | 1번 이상 반복을 매칭합니다. |
? | 0번 또는 1번 반복을 매칭합니다. |
| | | 두 표현식 중 하나를 매칭합니다(OR). |
| () | 그룹화하여 수량자를 적용합니다. |
{n} | 정확히 n번 반복을 매칭합니다. |
{n,} | n번 이상 반복을 매칭합니다. |
{n,m} | n번에서 m번 사이의 반복을 매칭합니다. |
a*: 'a'가 0번 이상 반복되는 패턴 (예: "", "a", "aaa").(ab)+: "ab"가 1번 이상 반복되는 패턴 (예: "ab", "abab").colou?r: "colour" 또는 "color"를 매칭.| 패턴 | 설명 |
|---|---|
. | 모든 단일 문자를 매칭합니다 (줄바꿈 제외). |
\\s | 공백 문자 (space, tab, 줄 바꿈 등)를 나타냅니다. |
\\b | 단어의 시작 또는 끝을 가리키며, 특정 단어가 독립적으로 존재하는지 확인합니다. |
\\d | 숫자 ([0-9])를 나타냅니다. |
\\w | 알파벳, 숫자 또는 밑줄 문자 ([A-Za-z0-9_])를 나타냅니다. |
a\\d+: 'a' 뒤에 하나 이상의 숫자를 매칭. (예: "a1", "a123").\\bword\\b: "word"라는 단어가 독립적으로 존재하는지 매칭. (예: "word", "the word")| 패턴 | 설명 |
|---|---|
[:digit:] | 숫자 ([0-9])를 매칭합니다. |
[:alpha:] | 알파벳 문자 ([A-Za-z])를 매칭합니다. |
[:alnum:] | 알파벳이나 숫자 ([A-Za-z0-9])를 매칭합니다. |
[:space:] | 공백 문자 (공백, 탭, 줄바꿈 등)를 매칭합니다. |
[[:digit:]]+: 하나 이상의 숫자를 매칭. (예: "123")[[:alpha:]]{3}: 알파벳 문자 3개를 매칭. (예: "abc")[[:alnum:]]*: 알파벳이나 숫자가 0번 이상 나오는 패턴을 매칭. (예: "", "abc123")[[:space:]]: 공백 문자를 매칭. (예: " ", "\t")정규 표현식을 사용한 문제 해결
문제에서 찾고 싶은 패턴은 DIAB1 이라는 prefix를 찾아내는 것이다.
pattern 1 : condition의 시작에 DIAB1 이 있는 경우이다.
DIAB100 MYOPpattern 2 : condition의 중간에 (즉, 공백 뒤에) DIAB1 이 있는 경우이다.
ACNE DIAB100다양한 패턴을 적용해 해당 문제를 해결해 보자
1) 문자열의 시작(^)과 공백을 OR로 그룹화하여 패턴을 만든다
SELECT *
FROM Patients
WHERE conditions REGEXP '(^| )DIAB1';
SELECT *
FROM Patients
WHERE conditions REGEXP '^DIAB1|\\sDIAB1'
SELECT *
FROM Patients
WHERE conditions REGEXP '\\bDIAB1'
어려운데 LIKE 쓰면 안되나요?
SELECT *
FROM Patients
WHERE conditions LIKE 'DIAB1%' OR conditions LIKE '% DIAB1%'
1517. Find Users With Valid E-Mails
Write a solution to find the users who have valid emails.
A valid e-mail has a prefix name and a domain where:
1. The prefix name is a string that may contain letters (upper or lower case), digits,
underscore '_', period '.', and/or dash '-'. The prefix name must start with a letter.
2. The domain is '@leetcode.com'.
+---------+-----------+-------------------------+
| user_id | name | mail |
+---------+-----------+-------------------------+
| 1 | Winston | winston@leetcode.com |
| 2 | Jonathan | jonathanisgreat |
| 3 | Annabelle | bella-@leetcode.com |
| 4 | Sally | sally.come@leetcode.com |
| 5 | Marwan | quarz#2020@leetcode.com |
| 6 | David | david69@gmail.com |
| 7 | Shapiro | .shapo@leetcode.com |
+---------+-----------+-------------------------+
+---------+-----------+-------------------------+
| user_id | name | mail |
+---------+-----------+-------------------------+
| 1 | Winston | winston@leetcode.com |
| 3 | Annabelle | bella-@leetcode.com |
| 4 | Sally | sally.come@leetcode.com |
+---------+-----------+-------------------------+
1517번 문제는 찾아야 하는 패턴이 다양하고 복잡하기 때문에 LIKE를 사용하여 풀기에는 어려워 보인다.
정규 표현식을 사용한 풀이는 다음과 같다.
SELECT *
FROM Users
WHERE mail REGEXP '^[a-zA-Z][a-zA-Z0-9_.-]*@leetcode\\.com$'
정규 표현식을 나눠서 살펴보자.
^[a-zA-Z] : The prefix name must start with a letter.
[a-zA-Z0-9_.-]* : prefix name is a string that may contain letters (upper or lower case), digits, underscore '_', period '.', and/or dash '-'
@leetcode\\.com$ : The domain is '@leetcode.com'.
REGEXP와 다른 문자열 매칭 함수의 비교
REGEXP은 LIKE나 INSTR과 같은 다른 문자열 매칭 함수들보다 복잡하고 유연한 매칭을 지원하는 것이 큰 장점이다.
REGEXP는 기능적으로는 모든 매칭을 커버할 수 있지만, 간단한 패턴(single condition)의 경우는 LIKE가 REGEXP보다 빠르다.
반대로, 복잡한 패턴(multiple condition)의 경우는 REGEXP가 LIKE보다 빠르다.
따라서, 쿼리에서 찾고자 하는 문자열 패턴의 복잡도를 고려하여 적절한 함수를 사용하는 것이 좋다.