데이터 분석/SQL

[SQL] HackerRank Weather Observation Station 6, 7, 8, 9 - 정규표현식 활용

된장찌개냠냠 2024. 5. 21. 11:24
반응형

MySQL에서 활용되는 정규표현식 함수 REGEXP, REGEXP_LIKE 함수의 차이점에 대해서는 이전 포스팅([SQL] MySQL 정규 표현식 사용법 (REGEXP, REGEXP_LIKE 차이점))을 참고해 주세요. 

 

정규표현식 활용 HackerRank 문제 풀이

먼저, 이어지는 HackerRank 정규표현식 문제에서 공통으로 사용될 STATION 테이블의 구조입니다. HackerRank에서는 DBMS를 선택할 수 있는데 MySQL 기준으로 문제를 풀었습니다.

# STATION 테이블

| Field  | Type         |
|--------|--------------|
| ID     | NUMBER       |
| CITY   | VARCHAR2(21) |
| STATE  | VARCHAR2(2)  |
| LAT_N  | NUMBER       |
| LONG_W | NUMBER       |

 

문제: Weather Observation Station 6 

문제 링크: https://www.hackerrank.com/challenges/weather-observation-station-6/problem

 

Weather Observation Station 6 | HackerRank

Query a list of CITY names beginning with vowels (a, e, i, o, u).

www.hackerrank.com

Query the list of CITY names starting with vowels (i.e., a, e, i, o, or u) from STATION. Your result cannot contain duplicates.

 

STATION 테이블에서 a, e, i, o, u로 시작하는 도시 이름(city)을 출력하는 쿼리를 작성하는 문제입니다. like를 활용해서 1번 쿼리처럼 작성할 수도 있지만, 2번처럼 정규표현식을 활용해서 작성할 수 있습니다.

# 1번: like 활용
SELECT city FROM station
where city like 'a%' OR city like 'e%' OR city like 'i%'
OR city like 'o%' OR city like 'u%'

# 2번: 정규표현식 활용
SELECT city FROM station
where regexp_like(city, '^[aeiou]')

 

'^[aeiou]'에서 ^은 문자열의 시작을 의미하며, [ ]는 대괄호에 둘러싸인 문자(a, e, i, o, u) 중 하나를 의미합니다. 즉, regexp_like(city, '^[aeiou]')의 뜻은, 'city 컬럼의 값이 a, e, i, o, u 중 하나로 시작한다'는 뜻입니다.

 

이처럼 정규 표현식을 활용하면 훨씬 더 간결하게 쿼리를 작성할 수 있습니다. 다음 문제로 넘어가 보겠습니다.

 

 

문제: Weather Observation Station 7

문제 링크: https://www.hackerrank.com/challenges/weather-observation-station-7/problem

 

Weather Observation Station 7 | HackerRank

Query the list of CITY names ending with vowels (a, e, i, o, u) from STATION.

www.hackerrank.com

Query the list of CITY names ending with vowels (a, e, i, o, u) from STATION. Your result cannot contain duplicates.

 

이번에는 도시명(city)이 모음(a, e, i, o, u) 중 하나로 끝나면서 중복되지 않는 도시명을 추출하는 문제입니다. 앞선 Weather Observation Station 6 문제와 마찬가지로 LIKE 연산자를 활용할 수 있습니다. 하지만 이번에도 더 간편하게 정규표현식을 사용해 보겠습니다.

SELECT DISTINCT city FROM station
WHERE REGEXP_LIKE(city, '[aeiou]$', 'i') # 컬럼 collation에 따라 'i' 쓰지 않아도 될 수 있음

 

먼저 고유한(unique) 도시명을 추출하기 위해 DISTINCT를 사용했습니다. DISTINCT에 관해서는 아래 포스팅에서 착각하기 쉬운 내용을 정리해 두었으니 참고해 주세요.

2024.05.19 - [데이터 분석/SQL] - SQL 오래 사용해도 착각하기 쉬운 3가지 (COUNT(*), alias, DISTINCT)

 

그다음으로 정규표현식을 활용했습니다. '[aeiou]$'에서 달러 표시($)는 문자열의 끝을 의미합니다. 즉, 'a, e, i, o, u 중 하나로 끝이 나는'이라는 뜻을 가진 정규표현식인 거죠.

 

그럼 REGEXP_LIKE 함수의 3번째 인자로 들어간 'i'는 무엇일까요?

'i'는 대소문자 구분하지 않음(case-insensitivity)을 의미하는데요. 모음(a, e, i, o, u) 중 하나로 끝나면서 a가 아니라 A로 끝나도 찾아주라는 의미입니다. 당장 HackerRank 문제에서는 'i' 인자를 전달하지 않아도 정답으로 처리됩니다. 하지만 컬럼의 collation에 따라 REGEXP_LIKE가 대소문자를 구분할 수 있으므로 'i'를 써주는 것이 조금 더 명확한 코드일 것입니다.

 

 

문제: Weather Observation Station 8

문제 링크: https://www.hackerrank.com/challenges/weather-observation-station-8/problem

 

Weather Observation Station 8 | HackerRank

Query CITY names that start AND end with vowels.

www.hackerrank.com

Query the list of CITY names from STATION which have vowels (i.e., a, e, i, o, and u) as both their first and last characters. Your result cannot contain duplicates.

 

이번에는 모음 중 하나로 시작하고, 동시에 모음 중 하나로 끝이 나는 도시명(city)을 중복을 제거한 후 출력하는 문제입니다. 역시 다양한 정답이 가능한데요. 그중 3가지의 정답을 아래와 같이 작성해 봤습니다.

 

# 정답1: LEFT, RIGHT 함수 사용
SELECT DISTINCT city FROM station
WHERE LOWER(LEFT(city, 1)) in ('a', 'e', 'i', 'o', 'u')
AND LOWER(RIGHT(city, 1)) in ('a', 'e', 'i', 'o', 'u')

# 정답2: 정규표현식 사용
SELECT DISTINCT city FROM station
WHERE REGEXP_LIKE(city, '^[aeiou].*[aeiou]$', 'i')

# 정답3: 정규표현식, AND 사용
SELECT DISTINCT city FROM station
WHERE REGEXP_LIKE(city, '^[aeiou]', 'i')
AND REGEXP_LIKE(city, '[aeiou]$', 'i')

 

1번 정답은 문자열의 왼쪽, 오른쪽의 문자를 가져올 수 있는 LEFT, RIGHT 함수를 사용했습니다. HackerRank 기준으로 LOWER 함수를 사용하지 않아도 정답으로 처리되지만, 확실하게 하기 위해 소문자로 바꿔주는 LOWER 함수를 사용했습니다. 그리고 city 컬럼의 왼쪽 첫 번째 문자가 모음 중 하나인지 (LOWER(LEFT(city, 1)) in ('a', 'e', 'i', 'o', 'u')), 오른쪽 첫번째 문자가 모음 중 하나인지 (LOWER(RIGHT(city, 1)) in ('a', 'e', 'i', 'o', 'u')) 체크했습니다.

 

2번 정답은 Weather Observation Station 6, 7번 문제에서 사용했던 정규표현식을 활용해서 풀었습니다. 모음 중 하나로 시작(^[aeiou])하고, 모음 중 하나로 끝나는([aeiou]$) 도시명을 찾는 것이죠. 그 사이에 있는 .*는 우선 점(.)은 '줄 바꿈 문자가 아닌 모든 문자'를 의미합니다. 그리고 별표(*)는 특정 문자가 0회 이상 반복된다는 의미를 갖습니다. 따라서 .*는 임의의 문자가 0회 이상 나온다는 뜻이죠. 정리하면, ^[aeiou].*[aeiou]$ 는 모음으로 시작되고 특정 문자가 0번 이상 사이에 들어간 후 모음으로 끝난다는 정규표현식입니다. 위에서 설명한 것처럼 'i'는 대소문자 구분을 하지 않기 위함인데, HackerRank 기준 생략해도 무방합니다.

 

3번 정답은 정규표현식만으로 풀다가 풀리지 않을 때 이런 정답도 가능함을 보여주기 위해서입니다. 이런 문제를 보고 정규표현식으로 풀려고 할 때, ^[aeiou]$ 이렇게 적었는데 왜 안될까 하면서 멘붕에 빠질 수도 있습니다. .* 같은 방법이 생각나지 않을 때는 정규표현식을 반으로 쪼개서 3번과 같이 작성할 수도 있습니다. 

 

 

문제: Weather Observation Station 9

문제 링크: https://www.hackerrank.com/challenges/weather-observation-station-9/problem

 

Weather Observation Station 9 | HackerRank

Query an alphabetically ordered list of CITY names not starting with vowels.

www.hackerrank.com

Query the list of CITY names from STATION that do not start with vowels. Your result cannot contain duplicates.

 

이번에는 모음으로 시작하지 않는 고유한 도시명을 출력하는 문제입니다. 이 문제는 정규표현식으로 쉽게 풀 수 있습니다.

SELECT DISTINCT city FROM STATION
WHERE REGEXP_LIKE(city, '^[^aeiou]', 'i')

 

'^[^aeiou] 의 의미는 우선 대괄호 밖의 ^는 문자열의 시작을 의미합니다. 단, ^가 대괄호 안에 있을 때는 부정을 의미합니다. 즉, 'aeiou 중 어느 것으로도 시작하지 않는'의 의미가 되어버리는 거죠. NOT LIKE를 여러 번 반복하는 방식으로도 풀 수 있겠지만 코드는 조금 더 길어질 것 같습니다.

 

이번 포스팅에서는 HackerRank Weather Observation Station 문제 중 6번, 7번, 8번, 9번을 (주로 정규표현식을 활용해서) 풀어봤습니다.

 

Weather Observation Station 10, 11, 12번 문제풀이 바로가기

HackerRank 모든 문제 풀이 모음 바로가기

 

정확하고 꼼꼼하게 씁니다

마케팅, 데이터, 프로덕트, 스타트업, 일상, 유용한 정보 등에 대해 씁니다.

onemorepatty.tistory.com

모든 SQL 코딩테스트 문제 풀이 모음 바로가기

 

정확하고 꼼꼼하게 씁니다

마케팅, 데이터, 프로덕트, 스타트업, 일상, 유용한 정보 등에 대해 씁니다.

onemorepatty.tistory.com

 

반응형