본문 바로가기

[공부] 데이터 분석 활용

[SQL 강의] 러닝스푼즈 | SQL과 구글 시트로 배우는 데이터 리터러시 첫 걸음 (5) 보고서 작성

종합 보고서의 내용 및 순서

개요

1) 배경 및 이유 정리

- 만든 사람과 보는 사람의 얼라인을 먼저 정확히 맞추기 위함

- 보고서를 만들기 전에 보고를 받아볼 사람에게 '난 이렇게 이해하고 이런 내용을 정리하려고 하는데, 원하는게 이게 맞아?' 하고 반드시 방향이 맞는지 확인 후 보고서를 만들 것.

 

2) 참고사항

- 보고서를 작성하며 있었던 특이사항, 변수, 이슈 등에 대해 어떻게 정의하고 시작했는지 등을 사전에 안내

- 화이트데이, 발렌타인데이 등 평소와 다른 요일에 주문수가 많이 나왔을 경우처럼, 특별한 예외사항에 대해 사전 안내 (제외하고 진행하였다 등)

- 데이터 집계 기간, 주요항목 (EX. 주문수 중에서도 어떤 조건을 충족한 주문수인지 명확히 정의)

- 상황을 모두 알고있는 우리팀원들이 아니라, 타팀원이나 상위자에게까지 보고가 필요한 내용이라면 그 외 공유사항을 더 상세히 작성

 

3) 결론

- 분석 내용 요약 및 의견 요약하기

- 보는 사람이 가장 궁금해하는 부분이기 때문에 상단에 먼저 요약정리해주는 것

- 위의 배경과 참고사항을 알고 결론을 봐야 더 정확한 의미 전달이 가능해짐

(이력서에서도... 성과와 회고를 먼저 적어야 하는 이유일까?)

 

현황 파악

1) 데이터 통계 자료

- 분석의 근거가 되는 자료, 결론의 힌트가 되는 자료

- 어떤 부분에 문제가 있는지, 어떤 부분이 눈에 띄는 차이가 있는지 한 눈에 확인할 수 있도록.

- 사실상 가장 시간이 오래 걸리는 부분이지만, 보고서에는 그 중에서도 의미있는 자료(핵심 근거)만 싣는다.

 

분석

1) 가설 및 분석

- 어떻게 가설을 세웠는지, 그걸 증명하기 위해 어떤 데이터를 보았는지

- 그냥 자료(표, 차트 등)만 던질 경우 보는 사람이 다시 한 번 그 자료를 분석하기 위해 시간과 에너지를 써야 함. 자료를 붙일 때는 반드시 나의 해석을 함께 공유할 것

 

보고서 작성 시 주의해야 할 점

1. 목적을 달성할 수 있는 결론을 도출

- 성과분석이 목적이면, 성공했는지 여부를 작성

- 이슈파악이 목적이면, 원인이 무엇이었는지, 어떻게 개선할 수 있을지 작성

 

2. 애매한 표현보다는 객관적으로 전달

- ~인 것 같습니다 (X) ~인 것으로 확인하였습니다 (O)

 

3. 데이터 기반으로 가설을 증명

- 뽑은 데이터를 시각화해 자료로 활용

 

4. 보고서의 흐름과 생각의 흐름 일치

- A > B > C 의 순서에서 중간을 생략하지 말 것. 처음 보는 사람도 매끄럽게 전 과정을 이해할 수 있도록

 

5. 쉬운 단어 / 표현 사용

- 한 용어에 대해서도 다른 팀에서는 다른 용어를 사용할 수 있음. (배달비/배달팁...) 어떤 의미의 용어인지 명확히 할 것

- 용어 대신 문장 형태로 풀어서 써주는 것도 좋음 (길어지더라도 이해가 안되는 단어가 등장하는 것보다 나음)

 

보고서 예시

 

- 더 좋은 작성방법이 얼마든지 있을 수 있음. 나만의 보고서 작성법을 앞으로 디벨롭해나갈 것

 

위에서 이용된 표를 뽑는 쿼리

1. 월별 매출 비교하기

 

with sales_raw as
(SELECT
substr(cast(a.reserv_date as string),1,6) as part_month,
c.item_id,
c.product_name,
count(a.reserv_no) as cnt,
sum(b.sales) as sales
-- sum(sum(b.sales)) over (partition by substr(cast(a.reserv_date as string),1,6)) as dense_sum,
-- round( sum(b.sales) /sum(sum(b.sales)) over (partition by substr(cast(a.reserv_date as string),1,6)) *100,0) as portion
FROM `ls-data-literacy-301513.practice.reservation`a
left join `ls-data-literacy-301513.practice.order_info` b on a.reserv_no = b.reserv_no
left join `ls-data-literacy-301513.practice.item` c on c.item_id = b.item_id

where cast(cancel as string) = 'false'
group by 1,2,3
)

select
part_month,
item_id,
product_name,
cnt,
sales,
sum(sales) over (partition by part_month) as dense_sum,
round(sales/ sum(sales) over (partition by part_month)*100,0) as yearly_portion
from sales_raw
group by 1,2,3,4,5

 

<출력값>

part_month item_id product_name cnt sales dense_sum yearly_portion
201706 M0002 PASTA 1 24000 613000 4
201706 M0007 SALAD 1 30000 613000 5
201706 M0009 WINE 1 8000 613000 1
201706 M0001 SPECIAL_SET 3 144000 613000 23
201706 M0008 SANDWICH 1 10000 613000 2
201706 M0005 STEAK 3 385000 613000 63
201706 M0010 JUICE 1 12000 613000 2
201707 M0001 SPECIAL_SET 6 408000 1744000 23
201707 M0010 JUICE 3 36000 1744000 2
201707 M0002 PASTA 6 228000 1744000 13
201707 M0008 SANDWICH 4 70000 1744000 4
201707 M0003 PIZZA 4 102000 1744000 6
201707 M0005 STEAK 5 525000 1744000 30
201707 M0004 SEA_FOOD 3 175000 1744000 10
201707 M0006 SALAD_BAR 4 200000 1744000 11
201708 M0001 SPECIAL_SET 6 336000 1622000 21
201708 M0010 JUICE 2 42000 1622000 3
201708 M0005 STEAK 5 455000 1622000 28
201708 M0008 SANDWICH 5 90000 1622000 6
201708 M0006 SALAD_BAR 3 175000 1622000 11
201708 M0004 SEA_FOOD 4 225000 1622000 14
201708 M0002 PASTA 5 108000 1622000 7
201708 M0003 PIZZA 5 136000 1622000 8
201708 M0009 WINE 3 40000 1622000 2
201708 M0007 SALAD 1 15000 1622000 1
201709 M0005 STEAK 4 280000 1586000 18
201709 M0004 SEA_FOOD 4 300000 1586000 19
201709 M0003 PIZZA 8 238000 1586000 15
201709 M0002 PASTA 5 120000 1586000 8
201709 M0001 SPECIAL_SET 4 264000 1586000 17
201709 M0008 SANDWICH 2 30000 1586000 2
201709 M0010 JUICE 2 48000 1586000 3
201709 M0009 WINE 1 16000 1586000 1
201709 M0007 SALAD 2 90000 1586000 6
201709 M0006 SALAD_BAR 4 200000 1586000 13
201710 M0006 SALAD_BAR 6 425000 3333000 13
201710 M0005 STEAK 10 1120000 3333000 34
201710 M0004 SEA_FOOD 3 200000 3333000 6
201710 M0002 PASTA 9 336000 3333000 10
201710 M0007 SALAD 3 135000 3333000 4
201710 M0003 PIZZA 8 391000 3333000 12
201710 M0001 SPECIAL_SET 6 552000 3333000 17
201710 M0010 JUICE 4 102000 3333000 3
201710 M0009 WINE 1 32000 3333000 1
201710 M0008 SANDWICH 3 40000 3333000 1
201711 M0006 SALAD_BAR 5 400000 5197000 8
201711 M0008 SANDWICH 7 150000 5197000 3
201711 M0009 WINE 6 304000 5197000 6
201711 M0010 JUICE 5 174000 5197000 3
201711 M0005 STEAK 12 1715000 5197000 33
201711 M0004 SEA_FOOD 5 425000 5197000 8
201711 M0001 SPECIAL_SET 13 888000 5197000 17
201711 M0007 SALAD 4 105000 5197000 2
201711 M0002 PASTA 10 492000 5197000 9
201711 M0003 PIZZA 15 544000 5197000 10
201712 M0005 STEAK 42 4900000 10862000 45
201712 M0009 WINE 13 456000 10862000 4
201712 M0001 SPECIAL_SET 21 3216000 10862000 30
201712 M0008 SANDWICH 13 220000 10862000 2
201712 M0006 SALAD_BAR 9 675000 10862000 6
201712 M0003 PIZZA 8 255000 10862000 2
201712 M0004 SEA_FOOD 5 300000 10862000 3
201712 M0007 SALAD 3 150000 10862000 1
201712 M0002 PASTA 19 660000 10862000 6
201712 M0010 JUICE 2 30000 10862000 0

 

2. 총 상품의 주문취소율 대비 스페셜 세트의 주문취소율

with sales_raw as
(SELECT
substr(cast(a.reserv_date as string),1,6) as part_month,
case when c.item_id = 'M0001' then 'specail' else 'etc' end as item_type,
c.product_name,
count(a.reserv_no) as cnt,
count(case when cast(cancel as string) = 'true' then a.reserv_no end) as canceled_reserv_cnt,
count(case when cast(cancel as string) = 'false' then a.reserv_no end) as completed_reserv_cnt,
sum(b.sales) as sales
FROM `ls-data-literacy-301513.practice.reservation`a
left join `ls-data-literacy-301513.practice.order_info` b on a.reserv_no = b.reserv_no
left join `ls-data-literacy-301513.practice.item` c on c.item_id = b.item_id

--where cast(cancel as string) = 'false'
group by 1,2,3
)
select
part_month,
sum(cnt) as cnt,
sum(sales) as total_sales,
sum(case when item_type = 'specail' then sales end) as special_sales,
round(sum(case when item_type = 'specail' then sales end) / sum(sales) *100,0) as special_portion,
sum(case when item_type = 'specail' then canceled_reserv_cnt end) as special_canceled_reserv_cnt,
round(sum(case when item_type = 'specail' then canceled_reserv_cnt end) /sum(cnt)*100,1) as specail_cancel_rate,
sum(canceled_reserv_cnt) as canceled_cnt,
sum(completed_reserv_cnt) as completed_cnt,
round(sum(canceled_reserv_cnt)/sum(cnt)*100,1) as cancel_rate
from sales_raw
group by 1
order by 1
part_month cnt total_sales special_sales special_portion special_canceled_reserv_cnt specail_cancel_rate canceled_cnt completed_cnt cancel_rate
201706 13 613000 144000 23 0 0 2 11 15.4
201707 41 1744000 408000 23 0 0 6 35 14.6
201708 45 1622000 336000 21 0 0 6 39 13.3
201709 41 1586000 264000 17 0 0 5 36 12.2
201710 61 3333000 552000 17 0 0 8 53 13.1
201711 94 5197000 888000 17 0 0 12 82 12.8
201712 155 10862000 3216000 30 0 0 20 135 12.9

 


지난 번 wau 감소 분석 프로젝트에서도 느꼈지만...

 

실제로 실무에서 활용하게 될 sql은 문제풀이에서 보는 것보다

1) 훨씬 길고

2) 그렇지만 단순한 함수의 조합으로 (count, sum, avg, 곱셈 나눗셈 비율표현 등)

3) 각 지표를 정확한 데이터를 이용해 정의하고 (Z라는 목적을 위해, A를 B로 나누어 C의 의미를 가진 D 지표를 뽑겠다)

4) 오류가 없도록 정확하게 짜야 한다.

 

그렇게 뽑은 sql은 이후로 진행할 데이터 분석의 재료가 될 뿐이고.

 

지금은 이렇게 보고서 하나 쓰는 것도 시간이 얼마나 걸릴지 계산하게 되고 까마득하고 아득해보이지만...

실무에서 활용하기 시작하면 6개월에서 1년이면 충분히 능숙하고 자신있게 쓸 수 있게 되지 않을까 싶다.

 

이렇게 번갯불에 콩 볶듯 완강한 강의!

sql이나 구글시트 활용 부분은 예상보다도 훨씬 더 쉬워 아쉬웠지만, 마지막의 보고서 작성 챕터는 좋았다.

배민의 사업개발 팀에서 일하시는 분도 이 정도의 분석 스킬, 보고서 작성 능력으로 비즈니스 업무를 진행하는 데에 크게 무리가 없구나. 를 알게 되어 조금은 자신감이 생겼다. 

 

이 정도는 기본으로 치고, 이외에 더 엣지를 더하고 싶다면

1) 추가로 더 고도의 데이터 분석 스킬을 익히거나

2) 나만의 강점이 될 수 있는 다른 역량을 더 갈고닦아야 할 것이다.

 

화이팅!