[2.26.TIL] 갑자기 자신감이 샘이솟아리오레이비

Brave_ Oh·2025년 2월 26일
3

데이터_정규캠프

목록 보기
7/24

추진력 강한 하루

오늘 나는 뭔가 자신감이 넘쳤던 것 같다. 이틀 전까지 끙끙 매던 세션 문제 5개를 오늘 순식간에 풀었다.(답은 맞는진 모르겠다. 솔직히 틀려도 뭔가 당당하다) 또한 어제 만든 그래프들을 바탕으로 팀원들과 상의하여, 금요일에 있을 발표의 결론 부분을 맡아서 피피티를 제작했다. 내일은 아마 열심히 그걸 녹음하고 있지 않을까?

오늘은 어제의 아티클 스터디부터 시작해서 오늘 푼 코드 문제들, 그리고 준비된 발표에 대해서 이야기해보겠다.

데이터 시각화 101: 3. 데이터 속 거짓말 발견하기

보이는 것을 다 믿지 마라

지난 아티클에서 시각화된 자료의 힘을 확인할 수 있었다. 이번 팀플에서 나는 이 점을 실제로 느낄 수 있었는데, 텍스트나 차트로된 정보를 시각화했을 때, 팀원들은 해당 자료에 대해서 더 다양한 의견을 제안해내는 것을 보았기 때문이다. 데이터의 변화 추이를 통시적으로 보거나, 변수에 따른 지표의 변화를 한 눈에 볼 수 있기 때문에, 데이터의 시각화는 실제로 강한 힘을 갖고 있다.

하지만 우리의 눈이 우리를 속이기도 한다. 정확히는 이것은 '속임수'에 가까운, 의도된 왜곡이라고 말할 수 있겠다. 이 자료를 시각화한 이는 이것을 보는 사람들이 자신과 같은 것을 보고, 생각하길 바랄 것이다. 그 의도는 절대 잘못된 것이 아닌게, 그건 모든 시각화 자료의 목적일 것이다. 하지만 그것을 달성하는 방식이 세련되지 못할 뿐이다.

이런 속임수가 속된 말로 '짜치다'고 생각한다면, 이런 많은 자료를 우리가 오랜 시간 뚫어져라 볼 일이 없음을 기억하자. TV나 광고에서 이런 차트가 순식간에 지나가더라도 당신은 이 속임수를 꿰뚫어볼 수 있을까?

왜곡을 피하는 방법은 하나다. 자료를 만들고, 나아가 자료를 왜곡하는 목적이 무엇인지를 파악해보자. 이를 간파하는 것을 넘어, 그 자료를 둘러싼 사회적, 정치적 맥락까지 간파할 수 있는 인사이트를 얻을 수 있을 것이다.

근자감 가득한 객기의 쿼리 작성

오늘부터는 여기에도 쿼리를 같이 작성하며 이야기해보자. 총 4개의 문제를 오늘 풀었고, 그 풀이 근거에 대해서도 이야기해보겠다.

문제1 - 집계함수의 활용
조건1) 서버별, 월별 게임계정id 수를 중복값 없이 추출해주세요. 월은 첫 접속일자를 기준으로 계산해주세요. 월은 yyyy-mm의 형태로 추출해주세요.

SELECT serverno, datetime, COUNT(game_account_id) as account_count
FROM
(
SELECT serverno ,SUBSTR(first_login_date, 1, 7) as datetime, game_account_id
FROM users u
)a
group by 1, 2

나에게 이 문제에서 핵심은 group by였다. 접속일자의 입력 방식을 조작하는 건 문제가 없었는데, 기준을 2개 적용하는 것이 직관적으로 이해가 가지 않았던 것이다. 이걸 해결하는 것이 단순히 group by를 통해 2개의 기준으로 그룹화하는 거였음을 알았을 땐 허무함을 감추지 못했다.

문제3 - 집계함수와 조건절의 활용2
조건1) group by 절을 사용하여 서버별, 유저구분(기존/신규) 게임캐릭터id수를 구해주세요. 중복값을 허용하지 않는 고유한 갯수로 추출해주세요.
조건2) 기존/신규 기준→ 첫 접속일자가 2024-01-01 보다 작으면(미만) 기존유저, 그렇지 않은 경우 신규유저
조건3) 또한, 서버별 평균레벨을 함께 추출해주세요.

문제 3
SELECT serverno '서버',
CASE WHEN first_login_date <2024-01-01 then '기준유저'
else '신규유저' end as '유저구분',
COUNT(DISTINCT game_actor_id) '게임케릭터 수',
AVG(level) '서버별 평균레벨'
FROM users u
group by 1,2
ORDER BY serverno

이런 문제들에 접근할 때는 그래서 무슨 컬럼을 결과에 보여줄지를 먼저 생각하면 편하다. 이 풀이가 솔직히 맞는지는 모르겠지만, 풀이의 근거는 있었다. 조건 1은 그룹화를 진행할 기준으로 서버, 그리고 유저구분을 제시하고 있다. 조건 2는 그 기준 중 하나인 유저구분의 조건을 제시하고 있으며, 마지막으로 조건 3은 기준화된 서버별 평균레벨을 구하라고 했는데, 'level'이라는 용어가 SQL 기능에도 있기 때문에, 작은 따옴표를 써주는 것이 포인트이다.

문제4 - SubQuery의 활용 2번 문제를 having 이 아닌 인라인 뷰 subquery 를 사용하여, 추출해주세요.
조건1) 문제2번을 having 이 아닌 인라인 뷰 서브쿼리를 사용하여 추출해주세요.

SELECT first_login_date, cha_numb
from
(
SELECT first_login_date, COUNT(DISTINCT game_actor_id) as cha_numb
FROM users
group by first_login_date
)a
WHERE cha_numb > 10
group by 1
ORDER BY first_login_date

2번 문제의 변주이다. 참고로 2번 문제와 답안지도 같이 넣겠다.

조건1) group by 를 활용하여 first_login_date별 게임캐릭터수를 중복값 없이 구하고,
조건2) having 절을 사용하여 그 값이 10개를 초과하는 경우의 첫 접속일자 및 게임캐릭터id 개수를 추출해주세요.

SELECT first_login_date , count(distinct game_actor_id) as cha_numb
FROM users
group by first_login_date
HAVING cha_numb >10

HAVING을 사용하지 않고 서브쿼리를 인라인 뷰 서브쿼리, 즉 FROM 뒤로 서브쿼리를 작성해서 문제를 해결하는 것이 조건이다. 인라인 뷰 서브쿼리는 내가 원하는 조건이 적용된, 새로운 테이블을 만드는 것과 같다. 따라서 각 날짜별로 게임 캐릭터 수를 파악한 테이블을 만드는 것이 먼저다.

SELECT first_login_date, COUNT(DISTINCT game_actor_id) as cha_numb
FROM users
group by first_login_date

이렇게 뽑으면 각 날짜별로 처음 접속한 캐릭터의 수를 확인할 수 있는 두 컬럼의 테이블이 만들어진다. 여기에 캐릭터가 10개를 초과하는 날짜를 확인하는 WHERE 절을 추가하고, 그 날의 게임캐릭터 수를 다시 확인한다. 따라서 SELECT 절은 서브쿼리절과 동일하다.

문제5 - SubQuery의 응용
조건1) 레벨이 30 이상인 캐릭터를 기준으로, 게임계정 별 캐릭터 수를 중복값 없이 추출해주세요.
조건2) having 구문을 사용하여 캐릭터 수가 2 이상인 게임계정만 추출해주세요.
조건3) 인라인 뷰 서브쿼리를 활용하여 캐릭터 수 별 게임계정 개수를 중복값 없이 추출해주세요.

SELECT count_actor, COUNT(ID)
FROM
(
SELECT game_account_id ID , COUNT(DISTINCT game_actor_id) count_actor
FROM users
WHERE level > 30
GROUP BY game_account_id
HAVING count_actor > 2
)a
GROUP BY 1;

푸는게 재밌었던 쿼리였다. 왜냐하면 서브쿼리에서 작성한 select 절과 바깥의 select절이 반대로 작성하는 기분이 들었기 때문에, 성취감이 분명 있었다. 조건을 순서대로 따라간다면 충분히 작성할 수 있었다.

조건1) 레벨이 30 이상인 캐릭터를 기준으로, 게임계정 별 캐릭터 수를 중복값 없이 추출해주세요.

SELECT game_account_id ID , COUNT(DISTINCT game_actor_id) count_actor
FROM users
WHERE level > 30
GROUP BY game_account_id

근본이 되어주는 서브쿼리문이다. 게임계정을 기준으로 각 계정의 캐릭터 수를 계산하는 쿼리를 먼저 짜줬다.

조건2) having 구문을 사용하여 캐릭터 수가 2 이상인 게임계정만 추출해주세요.

SELECT game_account_id ID , COUNT(DISTINCT game_actor_id) count_actor
FROM users
WHERE level > 30
GROUP BY game_account_id
HAVING count_actor > 2

지시한대로 HAVING절을 추가하여 그룹화가 적용된 테이블에 캐릭터 수가 2개 이상이라는 추가 조건을 적용한다.

조건3) 인라인 뷰 서브쿼리를 활용하여 캐릭터 수 별 게임계정 개수를 중복값 없이 추출해주세요.

SELECT count_actor, COUNT(ID)
FROM
(
SELECT game_account_id ID , COUNT(DISTINCT game_actor_id) count_actor
FROM users
WHERE level > 30
GROUP BY game_account_id
HAVING count_actor > 2
)a
GROUP BY 1;

이후에는 조건 3에 맞게, 인라인 뷰 서브쿼리, 즉 서브쿼리를 테이블로 치환하여 다시 쿼리를 작성해야 한다. 그리고 서브쿼리가 게임계정별 캐릭터 수를 추출하는 것이었다면, 반대로 본 쿼리는 캐릭터 수 별 게임계정 개수를 구하는 것이었기 때문에, 처음 말한 것처럼 반대로 구하는 재미가 있었다.

사실 난 이런 거 질문을 정말 많이 안하는 편이라, 맘대로 후다닥 풀고는 놀라며 실실 웃다가, 내가 틀렸다는 풀이를 보고 멘붕이 오는 편이다. 아무래도 이번주 안에는 맨토님께 한 번 검수를 받아야 겠다.

팀플 진짜 재밌다고

오늘 팀플의 주제는 금요일에 있을 발표의 골자를 잡는 것이었다. 따라서 발표 구성은 어떻게 할 것이며, 그에 따라 어떤 페이지를 만들어야할지 각자 정했다. 나는 금요일에 제출할 영상을 녹화할 예정이기 때문에, 빠르게 영상을 만든 뒤 녹음을 따서 파이널컷으로 씌워 완성할 예정이다.

이커머스를 분석하는 즐거움을 알게 된 것 같다. '온라인' 상거래라는 점에서, 플랫폼은 고객의 모든 행동 로그를 파악할 수 있기 때문에, 날짜, 시간별로 행동 로그를 따서 통계를 내면 생각보다 그럴싸한 결과물이 나온다. 그 결과물을 바탕으로 취할 액션 전략을 구상하는 것이 정말 재미있다. 이런 새로운 재미를 배우는 것도 캠프의 즐거움이 아닐까?

이젠 길고 재미있게 쓸게...

TIL을 쓰는 건 이 캠프에서 내 재능을 살릴 수 있는 유일한 유희가 아닐까 싶다. 에디터 출신으로서 내 맘대로 글을 쓰는 일은 즐겁지만, 이 글을 누가 보지 않는다고 생각하면 조금은 아쉬움이 있다. 그래도 나와의 약속, 캠프와의 약속이라 생각하고 열심히 써보자.

profile
데이터 분석 애송이의 유쾌한 반란

0개의 댓글

관련 채용 정보