본문 바로가기

카테고리 없음

Databricks | 복잡한 데이터 변환 (Complex Transformations)

728x90
반응형

Spark SQL을 활용한 데이터 분석 실무에서는 단순한 테이블 조회를 넘어서 복잡한 구조의 데이터를 다루는 일이 자주 발생합니다. 이번 글에서는 Databricks 강의 중 5 - Complex Transformations 섹션을 바탕으로 JSON 파싱, 배열 처리, 구조체 해제, 조인, 피벗 테이블 등 Spark SQL에서 자주 활용되는 고급 기능들을 체계적으로 정리합니다.


🧷 0. Nested JSON 이란?

Nested JSON은 JSON 데이터 내부에 또 다른 JSON 객체(혹은 배열)가 중첩된 구조를 말합니다.

예를 들어, 다음은 Nested JSON의 전형적인 예입니다:

{ "user_id": "123", "device": "Linux", "ecommerce": { "purchase_revenue_in_usd": 1075.5, "items": [ { "item_id": "M_STAN_K", "quantity": 1 } ] } }
  • ecommerce는 또 다른 JSON 구조(= STRUCT)입니다.
  • items는 배열 안에 STRUCT들이 들어있는 형태입니다.

👉 이처럼 한 컬럼 안에 복합적인 데이터 구조가 들어있다면 일반 SQL처럼 단순히 조회할 수 없습니다. Spark SQL에서는 . 또는 : 같은 특수 문법을 사용해 이러한 구조를 정제(flatten) 할 수 있습니다.


🔹 1. "." 및 ":" 구문의 차이와 사용법

✅ . 구문

  • 대상: STRUCT 타입
  • 설명: 구조체 내부의 필드를 접근할 때 사용
  • 예시:
SELECT ecommerce.purchase_revenue_in_usd FROM parsed_events;

parsed_events 테이블에서 ecommerce가 STRUCT 타입인 경우, 내부 필드를 .으로 접근합니다.


✅ : 구문

  • 대상: JSON 문자열(JSON string)
  • 설명: 문자열로 저장된 JSON에서 key에 직접 접근할 때 사용
  • 예시:
 
SELECT value:event_name FROM events_strings WHERE value:event_name = "finalize";

 


🧩 2. JSON 문자열 → STRUCT로 파싱

Spark SQL은 from_json() 함수를 통해 문자열(JSON)을 STRUCT로 파싱할 수 있습니다. 먼저 스키마를 추출해야 합니다.

스키마 추출 및 적용

SELECT schema_of_json('{ ... JSON 예시 ... }') AS schema;

이후 파싱:

CREATE OR REPLACE TEMP VIEW parsed_events AS SELECT from_json(value, '<복잡한 STRUCT 스키마>') AS json FROM events_strings;

파싱된 STRUCT는 json.*으로 해제 가능합니다.


🔄 3. 배열 다루기 (explode / size)

Spark SQL에서 배열 컬럼을 다룰 때는 다음과 같은 함수들을 사용합니다.

함수설명
explode(array) 배열을 행으로 펼침
size(array) 배열 길이 반환
 
CREATE OR REPLACE TEMP VIEW exploded_events AS SELECT *, explode(items) AS item FROM parsed_events; SELECT * FROM exploded_events WHERE size(items) > 2;

🧵 4. 중첩 함수 조합 (collect_set, flatten, array_distinct)

특정 사용자의 장바구니 이력을 수집하려면 collect_set() 등 여러 함수를 함께 사용합니다.

SELECT user_id, array_distinct(flatten(collect_set(items.item_id))) AS cart_history FROM exploded_events GROUP BY user_id ORDER BY user_id;
  • collect_set() : 중복 없이 아이템 수집
  • flatten() : 중첩 배열 평탄화
  • array_distinct() : 최종 중복 제거

📌 event_name 이력까지 보고 싶다면:

SELECT user_id, collect_set(event_name) AS event_history, array_distinct(flatten(collect_set(items.item_id))) AS cart_history FROM exploded_events GROUP BY user_id ORDER BY user_id;

🔗 5. 테이블 조인 (Join)

Spark SQL은 SQL 표준의 JOIN을 모두 지원합니다 (INNER, LEFT, RIGHT 등).

CREATE OR REPLACE TEMP VIEW item_purchases AS SELECT * FROM (SELECT *, explode(items) AS item FROM sales) a INNER JOIN item_lookup b ON a.item.item_id = b.item_id;

아이템 정보와 매핑되는 이름 또는 추가 데이터를 조인할 때 유용합니다.


📊 6. 피벗 테이블 (Pivot)

PIVOT 구문은 행 데이터를 열로 변형해 집계 형태로 보여줄 수 있도록 합니다.

사용 예시

SELECT * FROM item_purchases PIVOT ( sum(item.quantity) FOR item_id IN ( 'P_FOAM_K', 'M_STAN_Q', 'M_STAN_K', ... ) );
  • sum(item.quantity) : 집계 함수
  • FOR item_id : 어떤 값을 기준으로 피벗할지 지정
  • IN (...) : 열로 만들 항목들 지정

이 결과는 각 아이템 ID 별 구매 수량을 컬럼으로 정리한 테이블을 생성합니다.


🧠 마무리 요약

항목주요 함수설명
JSON 파싱 schema_of_json, from_json 문자열 → STRUCT 변환
구조체 필드 접근 . STRUCT 내부 접근
JSON 키 접근 : JSON 문자열 내부 접근
배열 분해 explode, size 배열을 행으로, 길이 확인
이력 수집 collect_set, flatten, array_distinct 배열 수집 및 정리
테이블 연결 JOIN 데이터셋 병합
요약 분석 PIVOT 행 → 열 변환하여 집계
 

 

728x90
반응형