Hive 주문과 고객 데이터 조인하기

빅 데이터Beginner
지금 연습하기

소개

소매업체의 주문에는 무엇이 팔렸는지가 있지만 고객별 지역은 다른 테이블에 있습니다. 주문마다 지역 텍스트를 복사하면 같은 정보가 반복됩니다. 대신 조회할 때 주문의 고객 식별자를 고객 기록에 연결할 수 있습니다. 이 연산을 **조인(join)**이라고 합니다.

관계의 양쪽을 확인하고 결제 완료 주문에 지역을 추가하며, 고객을 찾을 수 없으면 어떻게 되는지 살펴본 뒤 지역별 매출 보고서를 만듭니다. 조인에는 의미 있는 일치 규칙이 필요합니다. 규칙이 없으면 관련 없는 행이 결합되어 보고서 값이 부풀려질 수 있습니다. 준비된 고객 테이블에는 고객 식별자마다 정확히 한 행이 있으므로 각 일치 주문은 고객 하나와 연결됩니다.

이번 실습은 정상 주문 여섯 건, 고객 두 명과 별도의 미일치 예제를 독립적으로 준비합니다. Hive와 Beeline도 준비되어 있습니다. SELECT, WHERE, 그룹화와 십진수 판매 계산은 알고 있어야 하며 조인 문법은 여기서 소개합니다. Java, Python 또는 다른 실습의 파일은 필요하지 않습니다. 터미널을 사용하세요.

일치 기준이 되는 키 찾기

이 단계에서는 두 테이블이 같은 고객을 어떻게 나타내는지 확인합니다. 로컬 작업 공간에서 시작합니다.

cd /home/labex/project

제공된 주문과 고객 기록을 살펴봅니다.

cat /home/labex/project/data/orders.csv
cat /home/labex/project/data/customers.csv

고객은 여러 번 주문할 수 있으므로 주문에는 customer_id가 반복됩니다. 고객 테이블에는 customer_id마다 한 기록이 있으며 c1은 East(동부), c2는 West(서부)에 있습니다. 이 식별자가 **조인 키(join key)**입니다. 같은 행 위치나 비슷해 보이는 이름은 믿을 만한 일치 규칙이 아닙니다.

Hive로 고객 조회 테이블을 읽고 저장합니다. Beeline의 -u는 서비스, -n은 사용자 이름, -e는 SQL 문장을 선택합니다. TSV 출력과 헤더 비활성화로 결과 행을 쉽게 저장할 수 있으며 >는 지정한 로컬 파일을 바꿉니다.

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e "SELECT customer_id, region FROM retail_joins.customers ORDER BY customer_id;" > /home/labex/project/output/customers.tsv
cat /home/labex/project/output/customers.tsv

탭으로 구분된 두 행 c1 East와 c2 West가 예상됩니다. 이제 주문 o1의 일치를 예상할 수 있습니다. c1 식별자는 East에 연결됩니다. o2의 c2는 West에 연결됩니다. 이 테이블은 주문 기록에 설명 맥락을 더하므로 흔히 차원(dimension) 또는 조회 테이블이라고 합니다.

이번 연습은 고유한 조회 키를 제공합니다. 실제 데이터셋에 중복된 고객 키가 있으면 주문마다 조인된 행이 여러 개 생겨 매출이 부풀려질 수 있습니다. 의도한 관계를 아는 것도 조인 검증의 일부입니다.

INNER JOIN으로 결제 완료 주문에 정보 추가하기

이 단계에서는 각 결제 완료 주문에 지역을 추가합니다. orders o는 테이블에 짧은 별칭(alias) o를 주고 customers c는 다른 테이블에 c를 줍니다. o.customer_id 같은 참조는 열이 어느 테이블에서 오는지 식별하며 두 테이블의 열 이름이 같을 때 특히 유용합니다.

INNER JOIN은 양쪽에 일치하는 항목이 있는 행을 유지합니다. 명시적인 ON o.customer_id = c.customer_id 조건이 일치 규칙입니다. 히어 도큐먼트로 전체 쿼리를 저장합니다. 셸은 따옴표로 묶인 시작 SQL과 끝 SQL 사이의 줄을 그대로 파일에 씁니다.

cat > /home/labex/project/queries/enriched-orders.sql <<'SQL'
SELECT o.order_id, o.customer_id, c.region,
       o.quantity * o.unit_price AS order_amount
FROM retail_joins.orders o
INNER JOIN retail_joins.customers c ON o.customer_id = c.customer_id
WHERE o.order_status = 'paid'
ORDER BY o.order_id;
SQL
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -f /home/labex/project/queries/enriched-orders.sql > /home/labex/project/output/enriched-orders.tsv
cat /home/labex/project/output/enriched-orders.tsv

파일 실행 옵션 -f는 저장한 SQL을 실행합니다. 다음 네 행이 예상됩니다.

주문 고객 지역 금액
o1 c1 East 20.00
o2 c2 West 25.00
o4 c1 East 50.00
o6 c2 West 30.00

결제 완료 주문 네 건 모두 고객 하나를 찾았습니다. 조인은 계산 금액을 바꾸지 않고 설명 정보를 추가했으며 금액 합계는 여전히 125.00입니다. INNER JOIN은 고객이 일치하지 않는 주문을 제외합니다. 정상 보고 데이터는 그대로 두도록 별도 예제로 이 경우를 관찰합니다.

LEFT JOIN으로 일치하지 않는 주문 유지하기

이 단계에서는 작은 독립 예제로 두 조인 유형을 비교합니다. 두 기록을 읽습니다.

cat /home/labex/project/data/example-orders.csv

example1은 c1을 참조하고 example2는 조회 기록이 없는 c_missing을 참조합니다. 실행하기 전에 INNER JOIN 결과를 예상해 보세요.

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e "SELECT o.order_id, o.customer_id, c.region
FROM retail_joins.example_orders o
INNER JOIN retail_joins.customers c ON o.customer_id = c.customer_id
ORDER BY o.order_id;" > /home/labex/project/output/example-inner.tsv
cat /home/labex/project/output/example-inner.tsv

East인 example1만 나타나야 합니다. INNER JOIN은 일치가 필요하므로 일치하지 않는 주문은 사라졌습니다.

LEFT JOIN은 오른쪽 테이블에 일치하는 키가 없어도 왼쪽 테이블의 모든 행을 유지합니다. 누락된 오른쪽 기록에서 오는 열은 NULL이 됩니다. 조인 선택만 바꿉니다.

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e "SELECT o.order_id, o.customer_id, c.region
FROM retail_joins.example_orders o
LEFT JOIN retail_joins.customers c ON o.customer_id = c.customer_id
ORDER BY o.order_id;" > /home/labex/project/output/example-left.tsv
cat /home/labex/project/output/example-left.tsv

이제 example1/c1/East와 example2/c_missing/NULL 두 행이 예상됩니다. NULL은 이름이 "NULL"인 알려진 지역이 아니라 조회 일치가 없다는 뜻입니다. 원래 고객 식별자는 왼쪽 테이블에서 유지되므로 해결되지 않은 고객을 식별할 수 있습니다.

INNER JOIN과 LEFT JOIN 중 무엇을 선택할지는 업무 결정입니다. 정상 데이터가 모두 일치하는 지역 보고서는 INNER JOIN을 사용할 수 있고, 데이터 품질 검토는 미해결 기록을 유지하기 위해 LEFT JOIN이 필요할 수 있습니다. 예제 테이블은 orders와 별개이므로 여섯 행의 판매 데이터나 매출을 바꾸지 않습니다.

지역별 판매 보고서의 합계 맞춰 보기

이 단계에서는 이미 배운 그룹화를 정보가 추가된 기록에 적용합니다. 조인은 지역을 제공하고 WHERE는 결제 완료 주문을 선택하며 GROUP BY는 해당 주문을 지역별로 합칩니다. 집계를 추가할 때도 명시적인 일치 조건을 유지하세요.

cat > /home/labex/project/queries/regional-sales.sql <<'SQL'
SELECT c.region, SUM(o.quantity * o.unit_price) AS revenue
FROM retail_joins.orders o
INNER JOIN retail_joins.customers c ON o.customer_id = c.customer_id
WHERE o.order_status = 'paid'
GROUP BY c.region
ORDER BY c.region;
SQL
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -f /home/labex/project/queries/regional-sales.sql > /home/labex/project/output/regional-sales.tsv
cat /home/labex/project/output/regional-sales.tsv

East 70.00과 West 55.00이 예상됩니다. 둘을 합치면 조인하지 않은 원본의 결제 완료 매출 125.00과 같습니다. 고객 키가 고유하고 모두 일치하므로 결제 완료 주문이 중복되거나 사라지지 않았습니다.

작은 변경 연습으로 10월 14일만의 지역별 금액을 예상해 보세요. 그룹화 전에 이미 배운 날짜 조건을 주문 행에 적용합니다.

cat > /home/labex/project/queries/regional-sales-one-day.sql <<'SQL'
SELECT c.region, SUM(o.quantity * o.unit_price) AS revenue
FROM retail_joins.orders o
INNER JOIN retail_joins.customers c ON o.customer_id = c.customer_id
WHERE o.order_status = 'paid' AND o.order_date = DATE '2026-10-14'
GROUP BY c.region
ORDER BY c.region;
SQL
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -f /home/labex/project/queries/regional-sales-one-day.sql > /home/labex/project/output/regional-sales-one-day.tsv
cat /home/labex/project/output/regional-sales-one-day.tsv

이제 East 20.00과 West 25.00이며 해당 날짜의 45.00과 맞아야 합니다. 일치 규칙은 유지했고 선택한 주문 행만 바뀌었습니다. 주 쿼리인 regional-sales.sql은 이틀 전체 보고서를 유지합니다.

이제 새 설명 열과 변하지 않은 업무 합계를 모두 설명할 수 있습니다. 다음에는 날짜 파티션으로 이러한 SQL 날짜 조건과 일일 파일의 정리 및 등록 방식을 연결합니다.

요약

주문을 고유한 고객 키에 연결하고 별칭으로 관계를 명확하게 표현했으며, 일치 항목이 없는 예제로 INNER JOIN과 LEFT JOIN을 비교했습니다. 이후 지역별 결제 완료 판매 합계를 원본과 맞추고 조인을 바꾸지 않은 채 날짜 조건을 변경했습니다. 다음에는 Hive 파티션 메타데이터로 일일 데이터를 정리합니다.