본문 바로가기

블로그/SQL

[MYSQL] mysql 5.7에서 Lag함수를 구현해 유저 리텐션 구하는 방법 및 쿼리

mysql 5.7에서는 Windwo function을 사용할 수 없어서, lag와 같은 함수를 구현하기 위해서는 스칼라 서브쿼리나 Self join의 방법을 통해서 구현해야 한다. 따라서 유저 리텐션을 Mysql5.7에서 구하기가 굉장히 난감했는데, 데이터를 서브쿼리를 구현할 수 있는 Bigquery나 다른 플랫폼으로 옮기기도 애매한 상황이었다. 

 

아래의 테이블을 보자.

user_id

로그인 일자
1 2021.03.01
1 2021.03.02
2 2021.03.02
2 2021.03.04
1 2021.04.06
4 2021.01.01
4 2021.03.01
2 2021.01.19

위 같은 테이블이 있을때, 요청 사항은 아래와 같다.

 

Q: user_id와 로그인 일자를 기반으로, 해당 user_id가 로그인 일자 이전에 가장 최근 로그인한 일자가 언제인지 알고 싶다.

-> 추측건대, 요청자가 유저의 최근접속 기록을 통해 유저의 앱 혹은 웹 접속 리텐션을 확인하려고 하는 것 같다.

 

-> 결국 분석가가 나타내야할 테이블 결과는 가장 최근 로그인 일자가 있으면, 로그인 기준으로  바로 이전 로그인 날짜를 계산한 아래와 같다.

 

user_id 로그인 일자 기준 로그인 이전의 최근 로그인 일자
1 2021.03.01 null
1 2021.03.02 2021.03.01
2 2021.03.02 2021.01.19
2 2021.03.04 2021.03.02
4 2021.01.01 null
4 2021.03.01 2021.01.01

여기서 기준 로그인 이전의 최근 로그인 날짜가 Null값이면, 회원은 초기 진입인것이고 두 날짜를 계산하여 유저가 몇일만에 다시 접속했는지 파악할 수 있다.

 

레퍼런스에서는 위 테이플을 표현할 수 있는 쿼리 방법이 3가지가 있다고 했는데(e.g., 스칼라 서브쿼리, Self join, @변수 사용), 나는 스칼라 서브쿼리를 활용한게 쿼리를 이해하기도 편해서 자주 활용하게 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
-- 스칼라서브쿼리 --
SELECT user_id
     , login_dt
     , (SELECT login_dt
          FROM t b
         WHERE b.user_id  = a.user_id
           AND b.login_dt < a.login_dt
         ORDER BY login_dt DESC
         LIMIT 1
        ) lag_dt
  FROM t a
 ORDER BY user_id, login_dt
;

(1) 스칼라 서브쿼리로 같은 유저 아이디 기준으로 최근 로그인 이전의 로그인 일자 테이블을 만들어준다. (where b.user_id  = a.user_id AND b.login_dt < a.login_dt) 

(2) ORDER BY를 통해 최근 로그인 이전의 로그인 일자값을 최근 날짜 순으로 정렬한다.

(3) 이때, LIMIT이 1인 이유는 최근 로그인 이전의 로그인 일자값 1개를 붙이기 위해서다. 여기서는 가장 최근의 날짜가 될 것이다.

 

 

Reference: http://www.gurubee.net/article/84304