해결된 질문
작성
·
71
0
안녕하세요,
강의 수강하면서 Weekly, Monthly Retention 쿼리를 작성해보았습니다!
그리고 질문이 하나 있는데,
첨부해드린 코드는 현재 첨부해드린 사진처럼 오류가 발생합니다. 그런데 Weekly Retention 쿼리를 전부 주석처리하면 Monthly Retention 쿼리는 정상 작동합니다.
반대로 Monthly Retention 쿼리를 주석처리하면 Weekly Retention 쿼리는 정상 작동합니다.
이 현상의 원리에 대한 감이 잡히지 않아서 질문드립니다!
그 외에 쿼리 관련해서 고칠 점이 있다면 편하게 말씀해주시면 감사하겠습니다!
WITH base AS (
SELECT
user_id,
user_pseudo_id,
event_name,
DATE(DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul')) AS event_date,
DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_datetime
FROM advanced.app_logs
WHERE
event_date BETWEEN "2022-08-01" AND "2022-11-03"
), first_week_and_diff AS (
SELECT
*,
-- DATE_DIFF(event_date, first_date, DAY) diff_of_day
DATE_DIFF(event_week, first_week, WEEK) diff_of_week
FROM (
SELECT
DISTINCT -- 일자별로 중복 제거
user_pseudo_id,
-- DATE_TRUNC
DATE_TRUNC(MIN(event_date) OVER (PARTITION BY user_pseudo_id), WEEK(MONDAY)) AS first_week,
MIN(event_date) OVER (PARTITION BY user_pseudo_id) AS first_date,
DATE_TRUNC(event_date, WEEK(MONDAY)) AS event_week,
event_date
FROM base
)
), first_month_and_diff AS (
SELECT
*,
-- DATE_DIFF(event_date, first_date, DAY) diff_of_day
DATE_DIFF(event_month, first_month, MONTH) AS diff_of_month
FROM (
SELECT
DISTINCT
user_pseudo_id,
--DATE_TRUNC
DATE_TRUNC(MIN(event_date) OVER (PARTITION BY user_pseudo_id), MONTH) AS first_month,
DATE_TRUNC(event_date, MONTH) AS event_month,
MIN(event_date) OVER (PARTITION BY user_pseudo_id) AS first_date,
event_date
FROM base
)
)
-- Weekly Retention
SELECT
*,
ROUND(SAFE_DIVIDE(user_cnt, first_cnt), 3) AS week_retention_rate
FROM (
SELECT
*,
FIRST_VALUE(user_cnt) OVER (ORDER BY diff_of_week) AS first_cnt
FROM (
SELECT
diff_of_week,
COUNT(DISTINCT user_pseudo_id) AS user_cnt
FROM first_week_and_diff
GROUP BY
diff_of_week
)
)
ORDER BY
diff_of_week;
-- 추가. Monthly Retention
SELECT
*,
ROUND(SAFE_DIVIDE(user_cnt, first_cnt), 3) AS month_retention_rate
FROM (
SELECT
*,
FIRST_VALUE(user_cnt) OVER (ORDER BY diff_of_month) AS first_cnt
FROM (
SELECT
diff_of_month,
COUNT(DISTINCT user_pseudo_id) AS user_cnt
FROM first_month_and_diff
GROUP BY
diff_of_month
)
)
ORDER BY
diff_of_month;
답변 2
1
안녕하세요! 쿼리 잘 작성해주셨네요!
지금 현상에 대해 설명해드릴게요.
BigQuery는 ;
을 기준으로 쿼리 블록을 나눕니다. ;가 쓰이면 새로운 쿼리가 시작된다는 의미입니다. 그래서 위 쿼리 블록에서 정의한 CTE 표현을 ; 이후에 있는 아래 쿼리에서(월별 리텐션) 참고하지 못하는 것입니다. 위클리를 주석처리하면 실행되는 이유는 WITH문과 Monthly Retention을 하나의 쿼리 블록으로 보는거고, 그래서 참조를 할 수 있게 됩니다.
쓰신다면 CTE로 리텐션을 2개 정의하고, 마지막 SELECT 구문에서 필요한 CTE를 명시해서 쓸 것 같네요
0
안녕하세요, 인프런 AI 인턴입니다.
lchb0506님, 질문해 주신 내용에 대해 답변드리겠습니다. 두 쿼리(Weekly Retention
과 Monthly Retention
)가 따로 실행될 때는 문제없이 작동하나, 같이 실행될 때 오류가 발생한다고 하셨습니다. 해당 문제는 SQL 환경에서 여러 쿼리를 동시에 실행할 때 동일한 테이블이나 서브쿼리가 반복 사용되어 충돌이 발생하기 때문일 수 있습니다. 특히, 임시 테이블이나 CTE(Common Table Expressions) 이름이 겹치면서 발생할 수 있습니다.
현재 사용하신 쿼리 구조에서 WITH
구문에 의해 정의된 first_week_and_diff
와 first_month_and_diff
가 같은 쿼리 블록 내에서 이미 사용되고, 최종적인 SELECT 구문에서도 중첩된 형태로 사용되면서 이러한 문제가 발생한 것으로 보입니다.
다음은 유사한 질문과 답변 URL입니다. 이 게시물들은 리텐션 쿼리를 다루면서 발생할 수 있는 여러 문제점들에 대한 해결책을 제시합니다:
3-7 리텐션 SQL 쿼리 작성하기 연습 (Weekly, Monthly)
해결 방법으로는 다른 CTE 이름을 사용하거나, 전체 쿼리 구조를 명확히 하여 각 쿼리를 별도로 실행하도록 작성하는 것이 좋습니다. 또한, 각 쿼리의 실행 순서를 명확히 하여 서로 영향을 미치지 않도록 설계하는 것도 좋은 방법입니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.