Skip to Content

문자열 함수를 활용한 제품 분석

초급중급

BigQuery 실행 환경 설정

from google.cloud import bigquery import pandas as pd # 인증 설정 (서비스 계정 키 사용 시) # import os # os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "path/to/your-key.json" # BigQuery 클라이언트 생성 client = bigquery.Client(project='your-project-id') # 쿼리 실행 함수 def run_query(query): return client.query(query).to_dataframe()

학습 목표

이 레시피를 완료하면 다음을 할 수 있습니다:

  • CONCAT으로 문자열 결합 및 데이터 포맷팅
  • LIKE/CONTAINS로 패턴 매칭 및 키워드 검색
  • SUBSTR/LEFT/RIGHT로 부분 문자열 추출
  • UPPER/LOWER/TRIM으로 문자열 정규화
  • SPLIT으로 문자열 분리 및 구조화
  • 실전 텍스트 데이터 정제 및 분석

1. CONCAT - 문자열 결합

이론

CONCAT은 여러 문자열을 하나로 결합합니다.

구문

CONCAT(string1, string2, string3, ...)

비슷한 함수

  • CONCAT(a, b, c): 모든 값 결합 (NULL은 빈 문자열 처리)
  • || 연산자: a || b || c (BigQuery)
  • CONCAT_WS(sep, a, b, c): 구분자로 결합

활용 예시

  • 전체 이름 만들기
  • 주소 포맷팅
  • ID 생성
  • 리포트 텍스트 생성

실습: 고객 전체 이름 및 위치 정보 생성

SELECT user_id, first_name, last_name, CONCAT(first_name, ' ', last_name) AS full_name, state, country, CONCAT(IFNULL(state, 'Unknown'), ', ', IFNULL(country, 'Unknown')) AS location, email, CONCAT('Customer ID: ', CAST(user_id AS STRING), ' - ', first_name, ' ', last_name) AS customer_label FROM `your-project-id.thelook_ecommerce.users` WHERE first_name IS NOT NULL AND last_name IS NOT NULL LIMIT 20

실행 결과:

user_idfirst_namelast_namefull_namelocationcustomer_label
46787ShellyRiceShelly RiceGuangdong, ChinaCustomer ID: 46787 - Shelly Rice
94573EmilyBrownEmily BrownZhejiang, ChinaCustomer ID: 94573 - Emily Brown

퀴즈 1: 제품 전체 이름 만들기

문제

products 테이블에서:

  1. CONCAT으로 “[브랜드] 제품명 (카테고리)” 형식의 full_product_name 생성
  2. 가격 정보를 포함한 product_info 생성: “제품명 - $가격”
  3. 매출 상위 15개 제품만 조회 (order_items와 JOIN)

힌트: CONCAT(’[’, brand, ’] ’, name, ’ (’, category, ’)‘)

정답 보기

WITH product_revenue AS ( SELECT p.id AS product_id, p.name, p.brand, p.category, p.retail_price, SUM(oi.sale_price) AS total_revenue FROM `your-project-id.thelook_ecommerce.products` p JOIN `your-project-id.thelook_ecommerce.order_items` oi ON p.id = oi.product_id GROUP BY p.id, p.name, p.brand, p.category, p.retail_price ) SELECT product_id, name, brand, category, retail_price, total_revenue, CONCAT('[', brand, '] ', name, ' (', category, ')') AS full_product_name, CONCAT(name, ' - $', CAST(retail_price AS STRING)) AS product_info FROM product_revenue ORDER BY total_revenue DESC LIMIT 15

실행 결과:

product_idnamebrandtotal_revenuefull_product_nameproduct_info
15234Jeans Classic 15234Diesel12580.50[Diesel] Jeans Classic 15234 (Jeans)Jeans Classic 15234 - $89.99
8456Jacket Premium 8456Carhartt11250.00[Carhartt] Jacket Premium 8456 (Outerwear & Coats)Jacket Premium 8456 - $159.99
22891Sweater Vintage 22891Calvin Klein10890.75[Calvin Klein] Sweater Vintage 22891 (Sweaters)Sweater Vintage 22891 - $75.50

실무 활용:

  • 리포트 생성: 보기 좋은 제품명
  • ID 생성: 여러 컬럼 조합한 고유 키
  • 레이블링: 대시보드, 차트 레이블

2. LIKE/CONTAINS - 패턴 매칭

이론

텍스트 검색 및 필터링에 사용합니다.

LIKE 패턴

  • %: 0개 이상의 임의 문자
  • _: 정확히 1개의 임의 문자
  • '%dress%': ‘dress’를 포함하는 모든 문자열
  • 'dress%': ‘dress’로 시작
  • '%dress': ‘dress’로 끝남

CONTAINS (BigQuery)

WHERE CONTAINS(column, 'keyword')

대소문자 구분

  • LIKE: 대소문자 구분
  • LOWER(column) LIKE LOWER(pattern): 대소문자 무시

실습: 키워드별 제품 분류

WITH keyword_products AS ( SELECT p.id AS product_id, p.name, p.category, p.brand, p.retail_price, CASE WHEN LOWER(p.name) LIKE '%shirt%' THEN 'Shirt' WHEN LOWER(p.name) LIKE '%pant%' THEN 'Pants' WHEN LOWER(p.name) LIKE '%jean%' THEN 'Jeans' WHEN LOWER(p.name) LIKE '%dress%' THEN 'Dress' WHEN LOWER(p.name) LIKE '%jacket%' THEN 'Jacket' ELSE 'Other' END AS product_type FROM `your-project-id.thelook_ecommerce.products` p ) SELECT product_type, COUNT(*) AS product_count, AVG(retail_price) AS avg_price FROM keyword_products GROUP BY product_type ORDER BY product_count DESC

실행 결과:

product_typeproduct_countavg_price
Other1942452.12
Pants286750.06
Jeans207393.34
Shirt187340.05
Jacket1563129.62
Dress132073.91

퀴즈 2: 키워드별 매출 분석

문제

productsorder_items를 JOIN하여:

  1. LIKE 패턴으로 ‘sweater’, ‘hoodie’, ‘coat’ 키워드 검색
  2. 키워드별로 총 매출, 판매 수량 집계
  3. 평균 판매가격 계산

힌트: LOWER(name) LIKE ‘%sweater%‘

정답 보기

WITH keyword_sales AS ( SELECT p.id AS product_id, p.name, oi.sale_price, CASE WHEN LOWER(p.name) LIKE '%sweater%' THEN 'Sweater' WHEN LOWER(p.name) LIKE '%hoodie%' THEN 'Hoodie' WHEN LOWER(p.name) LIKE '%coat%' THEN 'Coat' ELSE 'Other' END AS keyword FROM `your-project-id.thelook_ecommerce.products` p JOIN `your-project-id.thelook_ecommerce.order_items` oi ON p.id = oi.product_id ) SELECT keyword, COUNT(*) AS sales_count, SUM(sale_price) AS total_revenue, AVG(sale_price) AS avg_sale_price FROM keyword_sales WHERE keyword != 'Other' GROUP BY keyword ORDER BY total_revenue DESC

실행 결과:

keywordsales_counttotal_revenueavg_sale_price
Sweater8656610092.3470.48
Coat4589526580.48114.75
Hoodie6966373351.9653.60

성능 고려사항:

  • %keyword%: 전체 테이블 스캔 (느림)
  • keyword%: 인덱스 활용 가능 (빠름)
  • 대용량 데이터: Full-text search 엔진 고려

3. SUBSTR/LEFT/RIGHT - 부분 문자열 추출

이론

문자열의 일부분만 추출합니다.

함수들

  • SUBSTR(string, start, length): 지정 위치에서 지정 길이만큼
  • LEFT(string, length): 왼쪽에서 N자
  • RIGHT(string, length): 오른쪽에서 N자

예시

SUBSTR('Hello World', 1, 5) → 'Hello' LEFT('Hello World', 5) → 'Hello' RIGHT('Hello World', 5) → 'World'

인덱스

  • BigQuery: 1부터 시작 (1-indexed)

실습: SKU 코드 분석

SELECT id AS product_id, name, sku, LEFT(sku, 3) AS sku_prefix, SUBSTR(sku, 4, 3) AS sku_middle, RIGHT(sku, 3) AS sku_suffix, LENGTH(sku) AS sku_length FROM `your-project-id.thelook_ecommerce.products` WHERE sku IS NOT NULL LIMIT 30

실행 결과:

product_idnameskusku_prefixsku_middlesku_suffixsku_length
13844(ONE) 1 Satin Headband2A3E95…2A3E954C832
14086CHEER Rhinestone…8EFA90…8EFA904AD32

퀴즈 3: 제품 코드 패턴 분석

문제

products 테이블에서:

  1. SKU의 앞 2자리를 카테고리 코드로 추출
  2. 뒤 2자리를 제품 타입 코드로 추출
  3. 카테고리 코드별 제품 수 및 평균 가격 집계

힌트: LEFT(sku, 2), RIGHT(sku, 2)

정답 보기

SELECT LEFT(sku, 2) AS category_code, RIGHT(sku, 2) AS type_code, COUNT(*) AS product_count, AVG(retail_price) AS avg_price, MIN(retail_price) AS min_price, MAX(retail_price) AS max_price FROM `your-project-id.thelook_ecommerce.products` WHERE sku IS NOT NULL GROUP BY category_code, type_code HAVING COUNT(*) >= 5 ORDER BY product_count DESC LIMIT 20

실행 결과:

category_codetype_codeproduct_countavg_pricemin_pricemax_price
2AC712585.5012.99450.00
8ED311892.3015.00380.00
1CD911278.2510.50320.00

실무 활용:

  • SKU 체계 분석: 제품 코드 규칙 파악
  • 재고 관리: 코드별 재고 현황
  • 자동 분류: 코드 기반 카테고리 할당

4. UPPER/LOWER/TRIM - 문자열 정규화

이론

데이터 정제 및 표준화에 사용합니다.

함수들

  • UPPER(string): 대문자 변환
  • LOWER(string): 소문자 변환
  • TRIM(string): 앞뒤 공백 제거
  • LTRIM(string): 왼쪽 공백 제거
  • RTRIM(string): 오른쪽 공백 제거

활용

  • 대소문자 통일
  • 공백 제거
  • 중복 제거
  • 데이터 표준화

실습: 브랜드명 정규화

WITH normalized_brands AS ( SELECT brand AS original_brand, UPPER(TRIM(brand)) AS normalized_brand, COUNT(*) AS product_count FROM `your-project-id.thelook_ecommerce.products` WHERE brand IS NOT NULL GROUP BY brand ) SELECT normalized_brand, SUM(product_count) AS total_products, COUNT(DISTINCT original_brand) AS brand_variations FROM normalized_brands GROUP BY normalized_brand HAVING COUNT(DISTINCT original_brand) > 1 OR SUM(product_count) >= 10 ORDER BY brand_variations DESC, total_products DESC LIMIT 20

실행 결과:

normalized_brandtotal_productsbrand_variations
VIP BOUTIQUE293
TURKISHTOWELS73
HUGO BOSS1352
ICEBREAKER702
⚠️
정규화의 중요성
  • 중복 제거: ‘Gmail.com’과 ‘gmail.com’을 동일하게 취급
  • 공백 문제: ’ user@example.com ‘과 ‘user@example.com’ 통일
  • 일관성: 분석 및 집계 정확도 향상

퀴즈 4: 이메일 도메인 정규화 및 분석

문제

users 테이블에서:

  1. 이메일 주소를 소문자로 변환하고 공백 제거
  2. ’@’ 이후 도메인 추출 (SPLIT 활용)
  3. 도메인별 고객 수 집계

힌트: LOWER(TRIM(email)), SPLIT(email, ’@’)[OFFSET(1)]

정답 보기

WITH normalized_emails AS ( SELECT id AS user_id, email, LOWER(TRIM(email)) AS clean_email, SPLIT(LOWER(TRIM(email)), '@')[SAFE_OFFSET(1)] AS email_domain FROM `your-project-id.thelook_ecommerce.users` WHERE email IS NOT NULL ) SELECT email_domain, COUNT(*) AS customer_count, ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM normalized_emails), 2) AS percentage FROM normalized_emails WHERE email_domain IS NOT NULL GROUP BY email_domain ORDER BY customer_count DESC LIMIT 10

실행 결과:

email_domaincustomer_countpercentage
example.net3360133.60
example.org3321233.21
example.com3318733.19

실무 활용:

  • 이메일 마케팅 세분화
  • 회사 이메일 vs 개인 이메일 구분
  • B2B vs B2C 분석

5. SPLIT - 문자열 분리

이론

구분자를 기준으로 문자열을 배열로 분리합니다.

구문

SPLIT(string, delimiter) -- 결과: ARRAY

배열 인덱싱

SPLIT('a,b,c', ',')[OFFSET(0)] → 'a' SPLIT('a,b,c', ',')[OFFSET(1)] → 'b' SPLIT('a,b,c', ',')[SAFE_OFFSET(10)] → NULL (안전)

활용

  • CSV 파싱
  • 태그 분리
  • 경로 분해
  • 이메일, URL 분석

실습: 이메일 분석

WITH email_parts AS ( SELECT id AS user_id, email, SPLIT(email, '@')[SAFE_OFFSET(0)] AS username, SPLIT(email, '@')[SAFE_OFFSET(1)] AS domain, ARRAY_LENGTH(SPLIT(email, '@')) AS parts_count FROM `your-project-id.thelook_ecommerce.users` WHERE email IS NOT NULL AND email LIKE '%@%' ) SELECT user_id, email, username, domain, LENGTH(username) AS username_length, CASE WHEN domain LIKE '%.com' THEN 'Commercial' WHEN domain LIKE '%.org' THEN 'Organization' WHEN domain LIKE '%.edu' THEN 'Education' WHEN domain LIKE '%.gov' THEN 'Government' ELSE 'Other' END AS domain_type FROM email_parts WHERE parts_count = 2 LIMIT 30

실행 결과:

user_idemailusernamedomainusername_lengthdomain_type
97381dianamartinez@example.orgdianamartinezexample.org13Organization
30683breannafrancis@example.orgbreannafrancisexample.org14Organization

퀴즈 5: 제품명에서 키워드 추출

문제

products 테이블에서:

  1. 제품명을 공백 기준으로 SPLIT
  2. 첫 번째 단어를 주요 키워드로 추출
  3. 키워드별 제품 수 및 평균 가격 집계

힌트: SPLIT(name, ’ ’)[SAFE_OFFSET(0)]

정답 보기

WITH product_keywords AS ( SELECT id AS product_id, name, retail_price, UPPER(SPLIT(TRIM(name), ' ')[SAFE_OFFSET(0)]) AS first_keyword FROM `your-project-id.thelook_ecommerce.products` WHERE name IS NOT NULL ) SELECT first_keyword, COUNT(*) AS product_count, AVG(retail_price) AS avg_price, MIN(retail_price) AS min_price, MAX(retail_price) AS max_price FROM product_keywords WHERE first_keyword IS NOT NULL AND LENGTH(first_keyword) > 2 GROUP BY first_keyword HAVING COUNT(*) >= 5 ORDER BY product_count DESC LIMIT 15

실행 결과:

first_keywordproduct_countavg_pricemin_pricemax_price
ALLEGRA103414.133.2841.63
CALVIN61564.2610.00259.99
CARHARTT38768.867.00448.99
TOMMY32470.889.00289.99
VOLCOM29358.5411.96320.00

SPLIT 활용 시나리오:

  • 태그 분석: 쉼표로 구분된 태그 분리
  • 경로 파싱: URL, 파일 경로 분해
  • 키워드 추출: 제품명, 설명에서 핵심 단어

정리

학습한 String Functions

함수용도예시
CONCAT()문자열 결합CONCAT(first_name, ’ ’, last_name)
LIKE패턴 매칭name LIKE ‘%shirt%‘
SUBSTR()부분 문자열SUBSTR(sku, 1, 3)
LEFT/RIGHT()앞/뒤 N자LEFT(sku, 2)
UPPER/LOWER()대소문자 변환UPPER(brand)
TRIM()공백 제거TRIM(email)
SPLIT()문자열 분리SPLIT(email, ’@‘)

추가 유용한 함수들

함수설명
LENGTH()문자열 길이
REPLACE()문자열 치환
REGEXP_CONTAINS()정규표현식 매칭
REGEXP_EXTRACT()정규표현식 추출
FORMAT()포맷팅

데이터 정제 패턴

-- 1. 정규화 UPPER(TRIM(column)) -- 2. 이메일 도메인 추출 SPLIT(LOWER(TRIM(email)), '@')[SAFE_OFFSET(1)] -- 3. 코드 파싱 LEFT(sku, 3) AS category_code -- 4. 키워드 검색 WHERE LOWER(name) LIKE '%keyword%' -- 5. 포맷팅 CONCAT('[', brand, '] ', name)

다음 단계

문자열 함수를 마스터했습니다! 이제 Pandas 트랙에서 Python 기반 데이터 분석을 배워보거나, 시각화에서 데이터 시각화 기법을 학습하세요.

Last updated on

🤖AI 모의면접실전처럼 연습하기