Skip to content
isdnetworks
Go back

숫자가 안 맞아서 보니 기준이 달랐다

관리자 화면에 활성 사용자 4,102명이 나오는데 마케팅 쪽에서 받은 자료에는 5,880명이었다. 같은 것을 세는 줄 알았다.

Table of contents

Open Table of contents

세는 조건이 달랐다

화면 쪽 쿼리를 봤다.

SELECT COUNT(*) FROM user WHERE del_yn = 'N' AND last_login >= DATE_SUB(NOW(), INTERVAL 30 DAY);

30일 안에 접속한 사람이다. 마케팅 쪽 쿼리를 받아 봤다.

SELECT COUNT(*) FROM user WHERE del_yn = 'N';

탈퇴 안 한 사람 전부다. 둘 다 활성 사용자라고 부르고 있었으니 조건이 다르면 숫자가 다른 것이 당연했다.

어느 것이 맞나가 아니었다

처음에는 어느 쪽이 맞는지 정하려 했는데 따져 보니 둘 다 필요한 숫자였다.

30일 접속자는 지금 얼마나 쓰는지를 말하고 탈퇴 안 한 사람은 계정이 몇 개인지를 말한다. 어느 하나를 틀렸다고 하면 그쪽 용도가 사라진다.

문제는 둘을 같은 이름으로 부른 것이었고 그래서 이름을 셋으로 나눴다.

가입 회원      del_yn = 'N'
활성 회원      del_yn = 'N' AND last_login >= 30일
휴면 회원      del_yn = 'N' AND last_login < 90일

정의를 문서로 적었다

숫자를 쓰는 화면과 보고서가 여럿이라 정의를 한 곳에 적었다.

## 회원 수 정의

가입 회원   del_yn='N'
            탈퇴하지 않은 계정 전체

활성 회원   del_yn='N' AND last_login >= (오늘 - 30일)
            최근 30일 내 접속. 30일은 (근거: 월 단위 보고 주기)

휴면 회원   del_yn='N' AND last_login < (오늘 - 90일)
            90일 이상 미접속. 관련 규정에 따름

주의
- last_login 이 NULL 인 계정 = 가입 후 한 번도 접속 안 함. 활성에 안 들어감
- 탈퇴 회원은 어느 숫자에도 안 들어감

주의 항목이 중요했다. last_loginNULL 인 계정이 312개 있었는데 이것이 활성에 들어가는지가 사람마다 다르게 알고 있었다.

뷰와 시점 고정

정의를 적어도 각자 쿼리를 쓰면 또 어긋나서 뷰로 만들었다.

CREATE VIEW v_user_active AS
SELECT * FROM user
WHERE del_yn = 'N' AND last_login >= DATE_SUB(CURDATE(), INTERVAL 30 DAY);
SELECT COUNT(*) FROM v_user_active;

정의가 바뀌면 CREATE OR REPLACE VIEW 한 번으로 끝난다. 뷰가 느릴 수 있어서 실행 계획을 확인했는데 last_login 에 인덱스가 있어서 괜찮았다.

같은 쿼리를 다른 시각에 돌리면 숫자가 다른 것도 문제였다. NOW() 가 계속 바뀌니 경계가 움직인다. 보고서용은 CURDATE() 로 그날 자정 기준을 쓰게 해서 같은 날 안에서는 결과가 같게 했다.

일별 수치는 매일 새벽에 계산해서 표에 저장했다.

CREATE TABLE user_stat_daily (
  stat_date  DATE NOT NULL,
  total_cnt  INT NOT NULL,
  active_cnt INT NOT NULL,
  dormant_cnt INT NOT NULL,
  PRIMARY KEY (stat_date)
);

지난 수치를 다시 계산하면 값이 달라진다. 그때 활성이던 사람이 지금은 휴면일 수 있으니 user_stat_daily 에 저장해 둬야 그 시점 값이 남는다.

검증 — 다른 지표와 검산

회원 수를 정리하고 나서 다른 것도 봤다. 주문 건수는 취소 주문 포함인지가 갈렸고 매출은 배송비와 부가세 포함 여부가 갈렸으며 상품 수는 판매중지 포함인지가 갈렸다.

셋 다 화면마다 다르게 세고 있어서 같은 문서에 정의를 추가하니 지표가 열 개쯤 됐다.

정의를 정하고 나서 각 숫자가 맞물리는지도 봤다.

가입 회원  = 활성 + 비활성
비활성     = 휴면 + (30~90일 미접속)

세어 보니 12명이 안 맞았는데 last_login 이 미래 날짜인 계정이 있었고 시간대 처리 실수로 들어간 값이었다.

정의를 정하고 검산하니 그때까지 안 보이던 자료 오류가 드러난 것이다.

정리


Share this post on:

Previous Post
응답에 코드와 사유가 따로 있었다
Next Post
심볼 하나에 행이 셋이었다