dev course - DE/TIL
[데브코스] TIL 23일차
nani-jin
2024. 4. 24. 15:38
1. GROUP BY
- 테이블의 레코드를 그룹별로 묶어 계산할 수 있게함
- 두 단계로 이뤄짐
- 그룹핑을 할 필드를 결정해 GROUP BY로 지정(하나 이상의 필드 가능)
- 그룹별로 계산할 내용 결정
- 여기서 AGGREGATE 함수 사용
- COUNT, SUM, AVG, MIN, MAX, LISTAGG, ...
- 보통 함수 결과에 필드 이름을 지정함
- 예제(1) - 가장 많이 사용된 채널은 무엇인가?
- 많이 사용되었다의 1)정의는?
- 사용자 기반 vs. 세션 기반
- 2)필요한 정보 - 채널 정보, 사용자 정보 혹은 세션 정보
- 3)먼저 어느 테이블을 사용해야 하는지 생각해!
- user_session_channel?
- session_timestamp?
- 혹은 이 2개의 테이블을 조인해야하나?
- 많이 사용되었다의 1)정의는?
SELECT
channel,
COUNT(1) AS session_count,
COUNT(DISTINCT userId) AS user_count
FROM raw_data.user_session_channel
GROUP BY 1 -- GROUP BY channel
ORDER BY 2 DESC; -- ORDER BY session_count DESC
- 예제(2) - 월별 유니크한 사용자 수
- 1)정의
- MAU(Monthly Active User)에 해당
- 2)필요한 정보
- 시간 정보, 사용자 정보
- 3)먼저 어느 테이블을 사용해야 하는지 생각해!
- user_session_channel(userId, sessionId, channel)?
- session_timestamp(sessionId, ts)?
- 혹은 이 2개의 테이블을 조인해야하나?
- 1)정의
SELECT
TO_CHAR(A.ts, 'YYYY-MM') AS month,
COUNT(DISTINCT B.userId) AS mau -- 한 사용자가 1번을 방문했건 100번을 방문했건 유니크한 사용자 수
FROM raw_data.session_timestamp A
JOIN raw_data.user_session_channel B ON A.sessionid = B.sessionid
GROUP BY 1
ORDER BY 1 DESC;
-- string functions 장단점 --
TO_CHAR(A.ts, 'YYYY-MM') -- 문자열로 월만 받고싶을 때
LEFT(A.ts, 7)
SUBSTRING(A.ts,1,7)
DATE_TRUNC('month', A.ts) -- type : timestamp를 원할 때. 2020-04-01 00:00:00 해당 월에 첫날로 잘림
2. CTAS, CTE
- CTAS(CREATE TABLE AS SELECT)
- SELECT로 테이블을 쉽게 생성함
- 자주 JOIN되는 테이블들을 CTAS를 통해 미리 만들어두면 아주 편리함
- 세 개의 스키마 raw_data(외부에서 가져와 ETL한 데이터), analytics(raw_data의 테이블들을 조합해 쉽게 쓸 수 있는 새로운 layer), adhoc가 있을 때, 이런 조인된 테이블은 analytics로 들어감
DROP TABLE IF EXISTS adhoc.yj_session_summary;
CREATE TABLE adhoc.yj_session_summary AS -- CTAS
SELECT B.*, A.ts
FROM raw_data.session_timestamp A
JOIN raw_data.user_session_channel B ON A.sessionid = B.sessionid;
- CTE(Common Table Expression)
- 권한이 필요 없고 하나의 쿼리문이 끝날때까지만 지속되는 일회성 테이블을 만들 수 있음
With ds AS (
SELECT DISTINCT userId, sessionId, ts, channel
FROM adhoc.yj_session_summary
)
SELECT COUNT(1)
FROM ds;
3. 항상 시도해봐야하는 데이터 품질 확인 방법!
- 중복된 레코드 체크
-- 1. 중복된 레코드 체크 -- 다음 두 개의 카운트를 비교 --
SELECT COUNT(1)
FROM adhoc.yj_session_summary;
SELECT COUNT(1)
FROM (
SELECT DISTINCT userId, sessionId, ts, channel
FROM adhoc.yj_session_summary
);
- 최근 데이터 존재하는지 체크(freshness)
-- 2. 최근 데이터 존재하는지 체크(freshness) --
SELECT MIN(ts), MAX(ts)
FROM adhoc.yj_session_summary
- primary key uniqueness 체크
-- 3. primary key uniqueness 체크 --
SELECT sessionId, COUNT(1) -- sessionId가 primary key. COUNT 값이 1보다 크면, 중복이 있다는 것
FROM adhoc.yj_session_summary
GROUP BY 1
ORDER BY 2 DESC
LIMIT 1;
- 값이 비어있는 컬럼이 있는지 체크
-- 4. 값이 비어있는 컬럼이 있는지 체크 --
SELECT
COUNT(CASE WHEN sessionId is NULL THEN 1 END) sessionid_null_count,
COUNT(CASE WHEN userId is NULL THEN 1 END) userid_null_count,
COUNT(CASE WHEN ts is NULL THEN 1 END) ts_null_count,
COUNT(CASE WHEN channel is NULL THEN 1 END) channel_null_count
FROM adhoc.yj_session_summary;
4. 새 테이블 소개
Table | Fields |
session_timestamp | sessionId(string), ts(timestamp) |
user_session_channel | userId(integer), sessionId(string), channel(string) |
session_transaction | sessionId(string), refunded(boolean), amount(integer) |
channel | channelname(string) |
- 숙제 - 채널별 월 매출액 테이블 만들기(본인 스키마 밑에 CTAS로 테이블 만들기)
- session_timestamp, user_session_channel, session_transaction 테이블 사용
- 아래와 같은 필드로 구성
- month
- channel
- uniqueUsers (총 방문 사용자)
- paidUsers(구매 사용자. refund한 경우도 판매로 고려함)
- conversionRate(구매 사용자 / 총 방문 사용자)
- grossRevenue(refund 포함)
- netRevenue(refund 제외)