[SQL분석] Google Big Query

Aiden·2024년 3월 6일
0

SQL분석

목록 보기
2/2

Google Big Query

  • 구글에서 제공하는 클라우드 데이터 웨어하우스
  • Data Warehouse : 분석용 중앙 데이터 창고의 개념
    - 서비스와 직접적으로 연결되어 있는 DB가 아닌 분석용 DB를 사용
    - SQL 활용
  • 빅쿼리 접속 URL : https://console.cloud.google.com/bigquery
  • 프로젝트 제작
    - 프로젝트 만들기 - 이름 설정 - 만들기
  • 프로젝트 구조
    - 프로젝트 - 데이터세트 - 테이블
  • 쿼리
    - SQL 쿼리 만들기 - 쿼리 입력창 / 쿼리 결과창
  • 쿼리 실행
    - ; 사용해 여러 쿼리 실행 가능
    - 탭을 추가해서 여러 쿼리 작성 가능
    - 원하는 쿼리만 드래그해서 실행하는 것도 가능
    - 테이블 내에서 쿼리 버튼을 통해 바로 테이블이 FROM절에 세팅되도록 하는 것도 가능
  • 데이터셋 업로드
    - 프로젝트 ID - 점 세개 - 데이터 세트 만들기
    - ID 설정 - 리전(서울) - 데이터 세트 만들기
    - 데이터 세트 이동 - 테이블 만들기
    - 테이블 업로드
    - 소스 - 업로드 (customers, items, orders, products, category_name)
    - 테이블 이름 설정
    - 스키마 - 자동 감지 (수동 설정도 가능) -> 테이블 만들기
    - ** 특수 테이블
    - 번역 파일 (category_name)
    - 스키마 직접 작성
  • 지표 쪼개기
    - 큰 지표 -> 작은 지표 (디테일)
    - 큰 지표를 설정하고 이 큰 지표를 추가로 확인할 수 있는 작은 지표로 쪼개서 분석
    - 매출 = 주문건수 건당 평균 주문 금액
    - 주문건수 = 주문고객수
    주문빈도
    - 건당 평균 주문 금액 = 판매품목수 * 물품평균가격
  • 쿼리 분석
    - 매출 = 판매 금액 총합
    - olist_order_items -> price
    - 주문 수 = 주문 건수 세기
    - olist_order_items -> order_id
    - 건당 주문 금액 = 판매 금액 총합 / 주문 건수 세기
    - 쿼리
    		```sql
    		SELECT
    			SUM(price) AS ord_amt, -- 주문 금액 총합 (매출)
    			COUNT(DISTINCT order_id) AS unique_orders, -- 전체 주문 건수
    			SUM(price) / COUNT(DISTINCT order_id) AS amount_per_order 
    			-- 주문 금액 총합 / 주문 건수 (주문 1건당 평균 가격)
    		FROM `olist.olist_order_items` ;
	- 주문 수 = 고객 수 * 주문빈도
		- 고객 수
			- olist_customers -> customer_unique_id
			- olist_orders -> customer_id
			- 2개 테이블 조인
			- 쿼리
				```sql
				/* 주문 고객 unique 세기 */
				SELECT
					COUNT(DISTINCT ord.order_id) AS ord_cnt, -- 주문 건수
					COUNT(DISTINCT ord.customer_id) AS cust_cnt,
					-- 참고. 주문건의 고객 id 세기 (주문건수와 동일)
					COUNT(DISTINCT cust.customer_unique_id) AS unique_cust_cnt
					-- 고객 고유 id 세기
				FROM `olist.olist_orders` AS ord -- 주문정보 테이블
				LEFT JOIN `olist.olist_customers` AS cust -- 고객정보 테이블
					ON ord.customer_id = cust.customer_id ; -- join 조건 : 주문 건의 고객 id
			```sql
			/* 주문 빈도까지 조회 */
			SELECT
				COUNT(DISTINCT ord.order_id) AS ord_cnt, -- 주문 건수
				COUNT(DISTINCT ord.customer_id) AS cust_cnt,
				-- 참고. 주문건의 고객 id 세기 (주문건수와 동일)
				COUNT(DISTINCT cust.customer_unique_id) AS unique_cust_cnt,
				-- 고객 고유 id 세기
				COUNT(DISTINCT order_id) / COUNT(DISTINCT cust.customer_unique_id) AS frequency -- 주문빈도
			FROM `olist.olist_orders` AS ord -- 주문정보 테이블
			LEFT JOIN `olist.olist_customers` AS cust -- 고객정보 테이블
				ON ord.customer_id = cust.customer_id ; -- join 조건 : 주문 건의 고객 id
				- ++ 한글로 Alias 설정하고 싶을 때는 AS `한글`의 형태로 (` 백틱) 입력
	- 건당 주문 금액 = 주문 건당 판매 품목 수 * 물품 평균 가격
		- 주문 건당 판매 품목 수 = 총 판매 상품 수 / 주문 건수
		- 물품 평균 가격 = 매출 / 총 판매 상품 수
		- 쿼리
			- 주문건수 : olist_order_items의 고유 order_id 수 세기
			- 총 판매 상품 수 : 판매 품목 수 세기 order_item_id
			- 매출 : 판매가격 전부 더하기 price
			```sql
			/* 총 매출, 주문건수 집계 */
			SELECT
				SUM(price) AS ord_amt, -- 주문 금액 총합 (매출)
				COUNT(DISTINCT order_id) AS unique_orders, -- 전체 주문 건수
				SUM(price) / COUNT(DISTINCT order_id) AS amount_per_order 
			-- 주문 금액 총합 / 주문 건수 (주문 1건당 평균 가격)
			FROM `olist.olist_order_items` ;
		```sql
		/* 총 판매 상품 수, 주문건수 집계 */
		SELECT
			COUNT(order_item_id) AS prd_cnt, -- 총 판매 상품 수
			COUNT(DISTINCT order_id) AS ord_cnt, -- 주문 건수
			COUNT(order_item_id) / COUNT(DISTINCT order_id) AS unit_per_order 
			-- 주문 당 평균 판매 상품 수
		FROM `olist.olist_order_items` AS ord ; -- 주문상품정보 테이블
			```sql
			/* 물품 평균 가격 집계 */
			SELECT
				SUM(price) AS ord_amt, -- 주문 금액 총합 (매출)
				COUNT(order_item_id) AS prd_cnt, -- 총 판매 상품 수
				SUM(price) / COUNT(order_item_id) AS average_selling_price 
				-- 판매 제품 당 평균 가격
			FROM `olist.olist_order_items` AS ord ; -- 주문상품정보 테이블
		```sql
		/* 합치기 */
		SELECT
			SUM(price) AS ord_amt, -- 주문 금액 총합 (매출)
			COUNT(DISTINCT order_id) AS unique_orders, -- 전체 주문 건수
			COUNT(order_item_id) AS prd_cnt, -- 총 판매 상품 수
			
			SUM(price) / COUNT(DISTINCT order_id) AS amount_per_order 
		-- 주문 금액 총합 / 주문 건수 (주문 1건당 평균 가격)
			COUNT(order_item_id) / COUNT(DISTINCT order_id) AS unit_per_order 
			-- 주문 당 평균 판매 상품 수
			SUM(price) / COUNT(order_item_id) AS average_selling_price 
			-- 판매 제품 당 평균 가격
		FROM `olist.olist_order_items` AS ord ; -- 주문상품정보 테이블
	- 종합 쿼리
		- 원하는 지표를 여러 테이블을 조인해 하나의 테이블로 표시
		1. 주문 1건 당 주문금액, 판매상품의 수 구하기
		2. 주문 정보 테이블에 1번 결과와 고객 unique ID를 붙이기
		3. 2번 결과 집계
		1. 주문 1건 당 주문금액, 판매상품의 수 구하기
		- 쿼리
		```sql
		SELECT
			item.order_id,
			SUM(item.price) as ord_amt,
			COUNT(item.order_item_id) as prd_cnt
		FROM `olist.olist_order_items` AS item -- 주문상품정보 테이블
		GROUP BY item.order_id -- 집계 기준 : 주문 번호
		
	2. 주문 정보 테이블에 1번 결과와 고객 unique ID를 붙이기
	- 쿼리
	```sql
	WITH tb AS(
	SELECT
		item.order_id,
		SUM(item.price) as ord_amt,
		COUNT(item.order_item_id) as prd_cnt
	FROM `olist.olist_order_items` AS item -- 주문상품정보 테이블
	GROUP BY item.order_id -- 집계 기준 : 주문 번호
	),

	SELECT
		ord.order_id,
		ord.order_status,
		cust.customer_unique_id,
		tb.ord_amt,
		tb.prd_cnt
	FROM `olist.olist_orders` AS ord -- 주문정보 테이블
	LEFT JOIN `olist.olist_customers` AS cust -- 고객정보 테이블
		ON ord.customer_id = cust.customer_id -- join 조건 : 주문 건의 고객 id
	INNER JOIN tb
		ON ord.order_id = tb.order_id ;
	
		3. 2번 결과 집계
		- 쿼리
		```sql
	WITH tb AS(
		SELECT
			item.order_id,
			SUM(item.price) as ord_amt,
			COUNT(item.order_item_id) as prd_cnt
		FROM `olist.olist_order_items` AS item -- 주문상품정보 테이블
		GROUP BY item.order_id -- 집계 기준 : 주문 번호
		)
			
	, base AS(
		SELECT
			ord.order_id,
			ord.order_status,
			cust.customer_unique_id,
			tb.ord_amt,
			tb.prd_cnt
		FROM `olist.olist_orders` AS ord -- 주문정보 테이블
		LEFT JOIN `olist.olist_customers` AS cust -- 고객정보 테이블
			ON ord.customer_id = cust.customer_id -- join 조건 : 주문 건의 고객 id
		INNER JOIN tb
			ON ord.order_id = tb.order_id
	)

	SELECT
		SUM(ord_amt) AS `총 매출`,
		COUNT(DISTINCT order_id) AS `총 주문수`,
		SUM(prd_cnt) AS `총 판매상품수`,
		SUM(ord_amt) / COUNT(DISTINCT order_id) AS `주문 당 평균가격`,
		SUM(prd_cnt) / COUNT(DISTINCT order_id) AS `평균 판매상품수`,
		SUM(ord_amt) / SUM(prd_cnt) AS `제품 개당 평균가격`,
		COUNT(DISTINCT customer_unique_id) AS `주문 고객수`,
		COUNT(DISTINCT order_id) / COUNT(DISTINCT customer_unique_id) AS `주문빈도`
	FROM base ;
  • 날짜
    - DATE : 2017-11-25
    - 쿼리
    			```sql
    			SELECT
    				DATE(2016, 12, 25) AS date_ymd,
    				DATE(DATETIME '2016-12-25 23:59:59') AS date_dt,
    				DATE(TIMESTAMP '2016-12-25 05:30:00+09', 'Asia/Seoul') AS date_tstz ;
	- DATETIME : 2017-11-25T11:10:33
		- 쿼리
			```sql
			SELECT
				DATETIME(2016, 12, 25, 05, 30, 00) AS datetime_ymdhms,
				DATETIME(TIMESTAMP '2016-12-25 05:30:00+09', 'Asia/Seoul') AS datetime_tstz ;
- TIMESTAMP : 2017-11-25 11:10:33 UTC
	- 타임존 포함 (한국 : UTC + 9)
- TIME : 11:10:33
- 빅쿼리 내 실제 쿼리
```sql
SELECT
	order_purchase_timestamp,

	DATE(order_purchase_timestamp) AS ord_date,

	DATETIME(order_purchase_timestamp) AS ord_date,

	TIMESTAMP(order_purchase_timestamp) AS ord_ts,
	TIMESTAMP(DATE(order_purchase_timestamp)) AS ord_date_ts,

	TIME(order_purchase_timestamp) AS ord_time
FROM `olist.olist_orders` ;
	- 날짜 일부분 추출
		- EXTRACT('추출할 부분' FROM '날짜 컬럼') -> 실행 시 숫자로 변경
			- 추출할 부분
				- YEAR : 연도
				- MONTH : 월
				- DAY : 일
				- DAYOFWEEK : 요일 (0:일요일 ~ 6:토요일)
				- WEEK : 주(기본 일요일 시작) - 0주부터 시작
				- WEEK(MONDAY) : 주(월요일 시작) - 0주부터 시작
				- QUARTER : 분기
				- HOUR : 시
				- MINUTE : 분
				- SECOND : 초
				```sql
				SELECT
					order_purchase_timestamp,
			
					EXTRACT(YEAR FROM order_purchase_timestamp)
				FROM `olist.olist_orders` ;
			```
	- 날짜에서 원하는 정보까지만 남길 때
		- DATE_TRUNC('날짜', '남기는 부분')
		- DATETIME_TRUNC('날짜', '남기는 부분')
		- TIMESTAMP_TRUNC('날짜', '남기는 부분')
			- 남기는 부분
				- YEAR : 해당 연도의 첫날
				- MONTH : 해당 월의 첫날
				- DAY : 해당 날짜의 0시 0분
				- WEEK : 해당 주차의 첫 날 (일요일)
				- WEEK(MONDAY) : 해당 주차의 첫 날 (월요일)
				- QUARTER : 분기
				- HOUR : 시
				- MINUTE : 분
				- SECOND : 초
				```sql
				SELECT
					order_purchase_timestamp,
			
					TIMESTAMP_TRUNC(order_purchase_timestamp, YEAR)
				FROM `olist.olist_orders` ;
			```
		- 종합 쿼리에 날짜 값 활용
		```sql
	WITH tb AS(
		SELECT
			item.order_id,
			SUM(item.price) as ord_amt,
			COUNT(item.order_item_id) as prd_cnt
		FROM `olist.olist_order_items` AS item -- 주문상품정보 테이블
		GROUP BY item.order_id -- 집계 기준 : 주문 번호
		)
			
	, base AS(
		SELECT
			ord.order_approved_at,
			DATE(ord.order_approved_at) AS ord_date,
			DATETIME(ord.order_approved_at) AS ord_dt,
			TIMESTAMP(ord.order_approved_at) AS ord_ts,
			EXTRACT(YEAR FROM ord.order_approved_at) AS ord_year,
			EXTRACT(MONTH FROM ord.order_approved_at) AS ord_month,
			TIMESTAMP_TRUNC(ord.order_approved_at, YEAR) AS ord_year_t,
			TIMESTAMP_TRUNC(ord.order_approved_at, MONTH) AS ord_month_t,
			ord.order_id,
			ord.order_status,
			cust.customer_unique_id,
			tb.ord_amt,
			tb.prd_cnt
		FROM `olist.olist_orders` AS ord -- 주문정보 테이블
		LEFT JOIN `olist.olist_customers` AS cust -- 고객정보 테이블
			ON ord.customer_id = cust.customer_id -- join 조건 : 주문 건의 고객 id
		INNER JOIN tb
			ON ord.order_id = tb.order_id
	)

SELECT
		ord_year,
		SUM(ord_amt) AS `총 매출`,
		COUNT(DISTINCT order_id) AS `총 주문수`,
		SUM(prd_cnt) AS `총 판매상품수`,
		SUM(ord_amt) / COUNT(DISTINCT order_id) AS `주문 당 평균가격`,
		SUM(prd_cnt) / COUNT(DISTINCT order_id) AS `평균 판매상품수`,
		SUM(ord_amt) / SUM(prd_cnt) AS `제품 개당 평균가격`,
		COUNT(DISTINCT customer_unique_id) AS `주문 고객수`,
		COUNT(DISTINCT order_id) / COUNT(DISTINCT customer_unique_id) AS `주문빈도`
	FROM base 
	GROUP BY ord_year
	ORDER BY ord_year ;
  • 유용한 함수
    - 원하는 컬럼만 불러오기
    - EXCEPT : 필요 없는 컬럼은 빼고 불러옴
    - SELECT EXCEPT('제외할 컬럼')
    - REPLACE : 기존 컬럼을 대체해서 표시됨
    - SELECT
    REPLACE('대체할 값' AS '컬럼명')
    - EX) SELECT REPLACE(price 10000 AS price)
    - 데이터 타입 변경
    - CAST('값' AS '데이터타입')
    - EX)
    - CAST('123' AS INT64)
    - CAST('abc' AS INT64) -> error
    - SAFE_CAST('값' AS '데이터타입')
    - EX)
    - SAFE_CAST('123' AS INT64)
    - SAFE_CAST('abc' AS INT64) -> null
    - ++ SAFE 활용 -> error가 아닌 Null 반환
    - SAFE_ADD(X, Y) = X + Y
    - SAFE_SUBTRACT(X, Y) = X - Y
    - SAFE_MULTIPLY(X, Y) = X * Y
    - SAFE_DIVIDE(X, Y) = X / Y -> 0으로 나누는 경우에 활용
    - IFNULL과 조합하면 null 값을 다른 값으로 변경하는 것도 가능
    - IFNULL('값', '변경 값')
  • 자주 쓰이는 IN / NOT IN
    - IN
    - WHERE '컬럼' IN (A, B, C)
    - NOT IN
    - WHER '컬럼' NOT IN (A, B, C)
    - 쿼리
    	```sql
    		WITH tb AS(
    	
    		SELECT
    	
    		item.order_id,
    	
    		SUM(item.price) as ord_amt,
    	
    		COUNT(item.order_item_id) as prd_cnt
    	
    		FROM `olist.olist_order_items` AS item -- 주문상품정보 테이블
    	
    		GROUP BY item.order_id -- 집계 기준 : 주문 번호
    	
    		)
    	
    		, base AS(
    	
    		SELECT
    	
    		DATE(ord.order_approved_at) AS ord_date,
    	
    		ord.order_id,
    	
    		ord.order_status,
    	
    		cust.customer_unique_id,
    	
    		tb.ord_amt,
    	
    		tb.prd_cnt
    	
    		FROM `olist.olist_orders` AS ord -- 주문정보 테이블
    	
    		LEFT JOIN `olist.olist_customers` AS cust -- 고객정보 테이블
    	
    		ON ord.customer_id = cust.customer_id -- join 조건 : 주문 건의 고객 id
    	
    		INNER JOIN tb
    	
    		ON ord.order_id = tb.order_id
    	
    		WHERE 1 = 1
    	
    		AND order_status IN ('delivered', 'shipped')
    	
    		AND order_approved_at IS NOT NULL
    	
    		)
    	
    	  
    	
    		SELECT
    	
    		ord_date,
    	
    		ROUND(SUM(ord_amt), 2) AS ord_amt, --총 매출
    	
    		COUNT(DISTINCT order_id) AS ord_cnt, --총 주문수
    	
    		SUM(prd_cnt) AS prd_cnt, --총 판매상품수
    	
    		ROUND(IFNULL(SAFE_DIVIDE(SUM(ord_amt), COUNT(DISTINCT order_id)), 0), 2) AS avg_ord_amt, --주문 당 평균가격
    	
    		ROUND(IFNULL(SAFE_DIVIDE(SUM(prd_cnt), COUNT(DISTINCT order_id)), 0), 2) AS avg_prd_cnt, --평균 판매상품수
    	
    		ROUND(IFNULL(SAFE_DIVIDE(SUM(ord_amt) , SUM(prd_cnt)), 0), 2) AS avg_price, --제품 개당 평균가격
    	
    		COUNT(DISTINCT customer_unique_id) AS cust_cnt, --주문 고객수
    	
    		ROUND(IFNULL(SAFE_DIVIDE(COUNT(DISTINCT order_id), COUNT(DISTINCT customer_unique_id)), 0), 2) AS cust_freq --주문빈도
    	
    		FROM base
    	
    		GROUP BY ord_date
    	
    		ORDER BY ord_date ;
- AD HOC QUERY
	- 요청사항 1
		- 주(state)별 침투율 확인 및 침투율이 낮은 지역을 중심으로 침투율 개선 예정
		- 주별 주문수와 고객수 추출 필요
		```sql
		/* 주(state)별 주문수, 고객수를 추출합니다. */

		-- 고객 정보 기준
		
		-- 주문 상태는 필터링하지 않음
		
		-- olist_orders, olist_customers 사용
		
		SELECT
		
		customer_state,
		
		COUNT(DISTINCT ord.order_id) AS ord_cnt,
		
		COUNT(DISTINCT cust.customer_unique_id) AS cust_cnt
		
		FROM `olist.olist_orders` AS ord
		
		LEFT JOIN `olist.olist_customers` AS cust
		
		ON ord.customer_id = cust.customer_id
		
		GROUP BY customer_state
		
		ORDER BY cust_cnt DESC ;
		```
	- 요청사항 2
		- 고객수 Top 2인 상파울루(SP), 리우데자네이루(RJ) 주만 필터링 (서브쿼리를 위한 join 연습)
		```sql
		/* 요청사항 2. 고객수 Top2 SP, RJ만 주문 추출 */
		
		-- 인라인 서브 쿼리 사용
		
		-- olist_orders, olist_customers 사용
		
		  
		
		SELECT
		
		ord.order_id,
		
		cust.customer_state
		
		FROM `olist.olist_orders` AS ord
		
		LEFT JOIN (SELECT customer_id,
		
		customer_unique_id,
		
		customer_state
		
		FROM `olist.olist_customers`
		
		WHERE customer_state IN ('SP', 'RJ')) AS cust
		
		ON ord.customer_id = cust.customer_id
		
		WHERE cust.customer_state IS NOT NULL ;
		
		-- WHERE 절은 olist_orders 테이블 기준 LEFT JOIN 이기 떄문에 olist_custmers 쪽 NULL 값 제외
		```
	- 요청사항 3
		- 현재 2018년 가정
		- 2017년 도시(city)별 주문수와 고객수, 매출 추출
			- 고객 수 기준 순위 표시
			- 전체 순위, 주(state) 내 순위 표시
			- 배송완료(delivered)된 건만 집계
		- 순위 쿼리
			- ROW_NUMBER() : 중복 없는 순위 (고유)
				- Ex) ROW_NUMBER() OVER (ORDER BY 컬럼 DESC)
			- RANK() : 동점일 때 중복 순위 (공동 등수)
				- 공동 순위자가 있다면 그 수 만큼 건너뛰고 다음 등수
			- DENSE_RANK() : 동점일 때 중복 순위 (공동 등수)
				- 공동 순위자가 있어도 연속으로 등수 설정
			- 사용법
				- OVER (ORDER BY [순위 조건])
					- 순위 조건 : 컬럼 & 오름차순, 내림차순 (ASC, DESC)
				- OVER (PARTITION BY [구분 기준] ORDER BY [순위 조건])
					- 구분 기준 : 구분이 필요한 컬럼
		```sql
		/* 요청사항 3. 2017년 도시(city)별 주문수, 고객수, 매출 */

		-- 현재 2018년 가정
		
		-- 고객 수 기준 내림차순 순위
		
		-- 순위는 전체 순위, 주(state) 기준 순위 모두 제공
		
		-- 배송완료 (order_status = 'delivered') 건만 집계
		
		  
		
		WITH tb AS(
		
		SELECT
		
		item.order_id,
		
		SUM(item.price) as ord_amt
		
		FROM `olist.olist_order_items` AS item -- 주문상품정보 테이블
		
		GROUP BY item.order_id -- 집계 기준 : 주문 번호
		
		)
		
		, base AS(
		
		SELECT
		
		cust.customer_state,
		
		cust.customer_city,
		
		COUNT(DISTINCT ord.order_id) AS ord_cnt,
		
		COUNT(DISTINCT cust.customer_unique_id) AS cust_cnt,
		
		SUM(tb.ord_amt) AS ord_amt
		
		FROM `olist.olist_orders` AS ord -- 주문정보 테이블
		
		INNER JOIN tb
		
		ON ord.order_id = tb.order_id
		
		LEFT JOIN `olist.olist_customers` AS cust -- 고객정보 테이블
		
		ON ord.customer_id = cust.customer_id -- join 조건 : 주문 건의 고객 id
		
		WHERE 1 = 1
		
		AND order_status = 'delivered'
		
		AND EXTRACT(YEAR FROM order_approved_at) = 2017
		
		GROUP BY 1, 2
		
		)
		
		SELECT
		
		*,
		
		ROW_NUMBER() OVER (PARTITION BY customer_state ORDER BY base.cust_cnt DESC) AS cust_rownum,
		
		DENSE_RANK() OVER (PARTITION BY customer_state ORDER BY base.cust_cnt DESC) AS cust_denserank,
		
		RANK() OVER (PARTITION BY customer_state ORDER BY base.cust_cnt DESC) AS state_rank,
		
		RANK() OVER (ORDER BY base.cust_cnt DESC) AS rank
		
		FROM base
		
		ORDER BY rank ;
- 요청사항 4
	- 고객별 객단가 (고객별 평균 금액)
	- 건 당 주문 금액 = 매출 / 고객 수
	```sql
	/* 요청사항 4. 고객 객단가 */

	-- 월 기준
	
	-- SAFE_DIVIDE 사용
	
	  
	
	SELECT
	
	DATE_TRUNC(DATE(ord.order_approved_at), MONTH) AS ord_month,
	
	SUM(item.price) AS ord_amt,
	
	COUNT(DISTINCT cust.customer_unique_id) AS cust_cnt,
	
	SAFE_DIVIDE(SUM(item.price), COUNT(DISTINCT cust.customer_unique_id)) AS avg_amt
	
	FROM `olist.olist_orders` AS ord
	
	INNER JOIN `olist.olist_order_items` AS item
	
	ON ord.order_id = item.order_id
	
	LEFT JOIN `olist.olist_customers` AS cust
	
	ON ord.customer_id = cust.customer_id
	
	GROUP BY ord_month
	
	ORDER BY ord_month ;
	```
- 요청사항 5
	- 월별 구입 금액에 기반해서 그룹 나누기
	- 그룹별 비중의 변화 확인
	- 월 - 고객 unique ID - 해당 월의 구매금액 - 그룹 순서
	- 300 BRL 이상 A, 150 BRL이상 300 BRL 미만 B, 그 외 C
		- CASE ~ WHEN 사용
		- Ex) CASE
				WHEN [조건 1] THEN [결과]
				ELSE [그외 결과]
			- END
	- order_status = delivered, shipped
	- order_approved_at IS NOT NULL
	```sql
	/* 요청사항5. 그룹별 월별 구입금액 */

	-- 월별 구입 금액에 기반해서 그룹 나누기
	
	-- 그룹별 비중의 변화 확인
	
	-- 월 - 고객 unique ID - 해당 월의 구매금액 - 그룹 순서
	
	-- 300 BRL 이상 A, 150 BRL이상 300 BRL 미만 B, 그 외 C
	
	-- order_status = delivered, shipped
	
	-- order_approved_at IS NOT NULL
	
	  
	
	SELECT
	
	DATE_TRUNC(DATE(ord.order_approved_at), MONTH) AS ord_month,
	
	cust.customer_unique_id AS cust_unique_id,
	
	SUM(item.price) AS ord_amt,
	
	CASE
	
	WHEN SUM(item.price) >= 300 THEN 'A'
	
	WHEN SUM(item.price) >= 150 THEN 'B'
	
	ELSE 'C'
	
	END AS level
	
	FROM `olist.olist_orders` AS ord
	
	INNER JOIN `olist.olist_order_items` AS item
	
	ON ord.order_id = item.order_id
	
	LEFT JOIN `olist.olist_customers` AS cust
	
	ON ord.customer_id = cust.customer_id
	
	WHERE 1=1
	
	AND ord.order_status IN ('delivered', 'shipped')
	
	AND ord.order_approved_at IS NOT NULL
	
	GROUP BY 1, 2
	
	ORDER BY ord_month, ord_amt DESC;
profile
aiden

0개의 댓글