묻고 답해요
135만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결처음하는 SQL과 데이터베이스(MySQL) 부트캠프 [입문부터 활용까지] (업데이트)
Dbeaver 라는 SQL 쿼리 실행 툴을 써도 될까요?
업무에선 Dbeaver로 자주 돌렸거든요.혹시 Workbench 말고 디비버도 괜찮을까요?
-
미해결초보자를 위한 BigQuery(SQL) 입문
Espanso 설치 후 터미널에서 편집 후 저장이 안됩니다(ESC :wq가 안먹어요.)
현재 이렇게까지 입력해놓은 상태인데,이 이후 ESC :wq가 인식이 안되고 ESC 누르고 콜론을 입력하면 에러 사운드가 뜨면서 밑에 Unknown Command 라는 안내 메시지가 뜹니다.어떻게 저장을 할 수 있을까요??
-
해결됨SW 개발자를 위한 성능 좋은 SQL 쿼리 작성법
부록 영상 질문
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.2:40 결과를 보도록 하겠습니다2:46 이제 SQL 서버의 기본 동작부터 보도록 하시죠 영상에서 2:40 -> 2:46 로 넘어가는 부분이 이해가 안 됩니다 ㅠㅠ 혹시 중간에 영상이 잘린 건가요??
-
미해결[백문이불여일타] 데이터 분석을 위한 중급 SQL
INNER JOIN 할 때 NULL 값이 안보일 수도 있나요?
저는 빈칸으로만 나오는데 null 값 표시가 따로 되지는 않네요
-
해결됨비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
실행 계획 type / 정렬 방식
안녕하세요 강사님! 실행 계획 type에 대해서 궁금한 점이 있습니다. ref가 UNIQUE가 아닌 컬럼의 인덱스를 사용한 경우라고 해주셨는데, 그러면 UNIQUE가 아닌 컬럼의 인덱스이지만 index나 range의 경우에 해당하면 해당 타입으로 표시되는 거고 저 둘(index, range)이 아닐 때, ref 타입으로 표시되는 걸까요? 그리고 한 가지 더 궁금한 점이 있는데, 만약 데이터를 조회한 결과들을 바로 View로 보내는 게 아니고 자바 코드를 사용한 계산을 통해 가공해야 하는 상황이라면 굳이 ORDER BY를 쓰지 않고, 데이터 조회 후, Collections.sort()와 같은 자바 코드로 정렬하는 편이 나을까요?
-
미해결[백문이불여일타] 데이터 분석을 위한 고급 SQL 문제풀이
SET4의 3번 자리바꾸기 문제 다른 풀이
선생님 강의 듣기 전에 나름대로 짱구를 굴려서 풀어 봤는데기본적으로 case when ~~~ 는 똑같지만lag, lead 함수를 활용해서 해도 문제 풀 수 있었어서공부하시는 분들과 같이 공유합니다.select id , case when mod(id, 2) = 1 and id in (select max(id) from seat) then student when mod(id, 2) = 0 then lag_stu when mod(id, 2) = 1 then lead_stu end as student from ( select a.id , a.student , lag(a.student) over(order by id) as lag_stu , lead(a.student) over(order by id) as lead_stu from seat a where 1=1 ) a where 1=1 order by 1
-
미해결SQL 시작도 못한 분들 드루와요
컬럼 추출이 안됩니다...!ㅠ
SELECT, FROM, ORDER BY, LIMIT 실습 파트 중입니다!mbtitest 테이블을 mbti_test로 다르게 설정하기는 했지만 다른 부분에 있어서는 동일하게 진행했습니다!그런데 컬럼 추출하려니까 에러가 떠서요그레이브를 잘 못 입력했나 싶기는 한데... 한 번 봐주시면 감사드리겠습니다!🙏T, F, ORDER BY, LIMIT 실습T,M, ORDER BY, LIMIT 실습
-
미해결처음하는 SQL과 데이터베이스(MySQL) 부트캠프 [입문부터 활용까지] (업데이트)
Sakila PDF 파일 오류
안녕하세요 Sakila 관련 PDF파일 네 파일 모두다 위에 열수 없다는 메세지가 뜹니다. 혹시 다시 올려주실 수 있나요?
-
미해결처음하는 SQL과 데이터베이스(MySQL) 부트캠프 [입문부터 활용까지] (업데이트)
SQL table에 있는 Default 의미
SQL table을 생성하면 Field, Type, Null, Key, Default, Ext순으로 있는데 Field, Type, Null, Key, Ext은 테이블 만들때 다 다뤘던거라 알겠는데 Dafult는 항상 NULL이라고 되어있는데 어떤건지 잘 모르겠더라구요. 그리고 NOT NULL이라고 데이터 형식을 적으면 NULL 에 Yes라고 뜨는데 Default에는 NULL이라고 되어있어서 가끔 헷갈리기도 하는 것 같아요. Default가 의미하는게 무엇이고, 왜 항상 NULL이라고 되어있는지 궁금합니다
-
해결됨초보자를 위한 BigQuery(SQL) 입문
4-5 시간 데이터 연습 문제 3번 질문
카일님, 안녕하세요! 시간 데이터 3번 문제 궁금한게 있어 질문드립니다.저는 해당 문제를 서브쿼리 없이 작성했는데, 서브쿼리 없이 작성해도 문제가 없나요?그리고 서브쿼리는 어떤 경우에 사용해야 하는지 기준이 있을까요??SELECT trainer_id, FORMAT_DATE("%d/%m/%Y", MIN(DATE(catch_datetime, 'Asia/Seoul'))) as first_date FROM basic.trainer_pokemon GROUP BY trainer_id ORDER BY trainer_id;
-
미해결BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
리텐션 과제_연습문제 2번
안녕하세요. 연습문제 2번을 다음과 같이 풀어보았습니다. Q: 리텐션 연습문제: Retain User를 New, Current, Resurrected, Dormant User로 나누는 쿼리를 작성하여라. 주어진 데이터에서 어떤 사람들이 리텐션이 그나마 높은지, 찾아보아라.주차별, 전체 유저에 대한 코호트 분석 그래프를 보면, 다음과 같습니다. 문제 정의2022년 12월 19일 이후로 리텐션이 떨어지고 있는 문제점이 발생했다. 해당 원인이 무엇일까?가설 설정1) 고객의 유입량이 감소하고 있다.-> 2022년 12월 19일 이전과 이후의 주차별 신규 가입자 수를 비교한다.2) 리텐션의 변화가 특정 유저 그룹에 의해 영향을 받는가?-> 신규유저는 어떤 시점을 기준으로 분류할 것인가?주차별 신규 가입자 수 시각화2022년 12월 19일을 월요일로 하는 주차부터 신규 가입자 수가 감소하는 추세이다. 전반적으로 신규가입자 수는 증가하는 추세였으나, 12월 19일을 기점으로 꺾이는 현상을 보인다. 따라서, 신규 가입자 수가 리텐션에 영향을 준다는 것을 확인할 수 있다.기존의 추세와 반하게, 떨어지는 추세를 보이기 때문에 다음과 같이 기존 유저와 신규 유저를 정의하겠다.1) 기존 유저=> 2022년 10월 03일 ~ 2022년 12월 19일 이전2) 신규 유저=> 2022년 12월 19일 이후복귀유저와 이탈 유저를 판단하는 기준이 필요하다. 이를 위해, 첫 로그인 이후, 두번째로 로그인을 하기까지의 걸리는 시간을 4분위 수로 검증해서, 중위값을 기준으로 기존유저와 복귀유저를 구분해보기로 했다.로그인 판단 기준 = click_login 이라는 이벤트가 발생했을 경우1. 자동 로그인 여부 판단SELECT COUNT(*) FROM advanced.app_logs CROSS JOIN UNNEST(event_params) AS ep WHERE ep.key = "firebase_screen" AND ep.value.string_value = 'welcome' AND user_id IS NOT NULL자동 로그인이 된다면, click_login 이벤트가 발생하지 않을 것이다. 하지만, COUNT(*)가 0이기 때문에, 해당 앱은 자동 로그인이 되지 않음을 알 수 있다.즉, 사용자가 앱에 접속하면, 가입을 했더라도, 무조건 로그인을 해야한다. 따라서, 사용자가 앱에 접속 시, 로그인 이벤트가 무조건 발생한다.2.첫번째 로그인 후, 다음 로그인하기까지 걸린 시간을 4분위 수로 계산WITH base AS (SELECT event_date, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_timestamp, user_pseudo_id, event_name, ROW_NUMBER() OVER (PARTITION BY user_pseudo_id ORDER BY event_date) AS login_rn FROM advanced.app_logs WHERE event_name = 'click_login' AND event_date >= '2022-10-03' QUALIFY login_rn < 3) , second_event_data AS (SELECT event_date, event_timestamp, user_pseudo_id, event_name, login_rn, IF(second_event_date IS NULL, '2023-01-20', second_event_date) AS second_event_date FROM (SELECT *, LEAD(event_date) OVER (PARTITION BY user_pseudo_id ORDER BY event_date) AS second_event_date FROM base)) SELECT APPROX_QUANTILES(date_diff_day, 100)[OFFSET(25)] AS percentile_25, APPROX_QUANTILES(date_diff_day, 100)[OFFSET(50)] AS percentile_50, APPROX_QUANTILES(date_diff_day, 100)[OFFSET(75)] AS percentile_75, MAX(date_diff_day) AS percentile_100, AVG(date_diff_day) AS average FROM (SELECT DATE_DIFF(second_event_date, event_date, DAY) AS date_diff_day FROM second_event_data)유저별로 로그인을 한 시점을 ROW_NUMBER()로 카운트했다. 또한, second_event_date(다음 로그인 시점)이 NULL인 경우는 이탈 유저이다. 그런데, 4분위 수를 계산하려면, 해당 값을 채워야했다. 2099-12-31로 하려고 했으나, 너무 큰 값을 채워버리면, 4분위 수 검증이 정확하지 않게 되기 때문에 (mid와 avg값이 오른쪽으로 치우쳐버리는 현상이 발생할 수 있다.) second_event_date의 max값을 구해서, 2023-01-20을 채워주었다.Approx_quantiles 함수는 백분위로 나눌 경우, 각 근사치의 최대값을 나타내는 함수이다. 중위값에 해당하는 값들 중 가장 큰 값은 39일이다. 이번에는, 해당 범위에 속하는 값들이 몇개가 있는지 확인해보겠다.SELECT COUNTIF(date_diff_day <= 19) AS count_up_to_25, COUNTIF(date_diff_day > 19 AND date_diff_day <= 39) AS count_25_to_50, COUNTIF(date_diff_day > 39 AND date_diff_day <= 66) AS count_50_to_75, COUNTIF(date_diff_day > 66 AND date_diff_day <= 109) AS count_75_to_100 FROM temp데이터가 1분위, 2분위에 몰려있다. 따라서, 40일 을 기준점으로 삼아야겠다.2022년 12월 19일 이후 ~ (신규유저)2022년 10월 3일 이후 ~ 2022년 12월 19일 이전, 10월 3일 이후부터 다음 접속 시간이 40일 이전인 경우 (기존유저)2022년 10월 3일 이후로부터 40일 이후로 접속한 유저(복귀유저)2022년 10월 3일 이후로부터 40일 이후로도 접속 이력이 없는 경우 (이탈 유저)3. 다음 접속일까지의 걸린 일 수 기반, 유저 분류-- 유저별, 첫번째 로그인 후, 다음 로그인하기 걸린 시간을 4분위 수로 계산 -- 25% | 50% | 75% | 100% -- 로그인_이벤트: click_login -- event_date, event_timestamp, event_name, -- 중간테이블 -- 유저별 로그인을 한 시점을 ROW_NUMBER()로 카운트하기 -- 유저별 첫번째 로그인을 한 시점 구하기 MIN(event_date) OVER() -- second_event_date가 NULL인 경우는 이탈 유저임. -- 그런데, 4분위 수를 계산하려면, MAX(second_event_date) 값을 구하고, NULL을 잠시 해당 값으로 채워놔야함. -- 그 이유는 너무 큰 값으로 채워버리면, 4분위 수 검증이 정확하지 않기 때문임 (mid값과 avg값이 오른쪽으로 치워쳐버리는 현상이 발생할 수 있음) max_event_date: 2023-01-20 WITH base AS (SELECT event_date, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_timestamp, user_pseudo_id, event_name, ROW_NUMBER() OVER (PARTITION BY user_pseudo_id ORDER BY event_date) AS login_rn FROM advanced.app_logs WHERE event_name = 'click_login' AND event_date > '2022-10-03' QUALIFY login_rn < 3) , second_event_data AS (SELECT DISTINCT event_date, event_timestamp, user_pseudo_id, event_name, login_rn, IF(second_event_date IS NULL, '2099-01-20', second_event_date) AS second_event_date FROM (SELECT *, LEAD(event_date) OVER (PARTITION BY user_pseudo_id ORDER BY event_date) AS second_event_date FROM base)) -- 접속 데이터 기반, 신규, 기존, 복귀, 이탈 구분 , user_type_data AS (SELECT event_date, second_event_date, user_pseudo_id, DATE_DIFF(second_event_date, event_date, DAY) AS comeback_day, CASE WHEN event_date >= DATE('2022-12-19') THEN '신규 유저' WHEN event_date >= DATE('2022-10-03') AND second_event_date <= DATE_ADD(event_date, INTERVAL 40 DAY) THEN '기존 유저' WHEN event_date >= DATE('2022-10-03') AND second_event_date > DATE_ADD(event_date, INTERVAL 40 DAY) AND second_event_date != DATE('2099-01-20') THEN '복귀 유저' WHEN event_date >= DATE('2022-10-03') AND second_event_date = DATE('2099-01-20') THEN '이탈 유저' ELSE NULL -- 예외 처리 END AS user_type FROM second_event_data) 4. 각 유저 타입별 리텐션 계산기존 유저-- 일자별 리텐션 계산 (기존 유저) , analysis_current AS (SELECT diff_of_day, COUNT(DISTINCT user_pseudo_id) AS user_cnt FROM (SELECT user_pseudo_id, MIN(event_date) OVER (PARTITION BY user_pseudo_id) AS first_day, event_date, comeback_day as diff_of_day FROM user_type_data WHERE user_type = '기존 유저' ORDER BY event_date, second_event_date) GROUP BY 1) SELECT diff_of_day, user_cnt, first_user_cnt, ROUND(SAFE_DIVIDE(user_cnt, first_user_cnt), 3) AS retention_day_rate FROM (SELECT diff_of_day, user_cnt, FIRST_VALUE(user_cnt) OVER (ORDER BY diff_of_day) AS first_user_cnt FROM analysis_current)복귀 유저신규 유저이탈 유저리텐션이 평평하게 안나오네요... 뭔가 단단히 잘못된것 같습니다..
-
미해결데이터 분석 SQL Fundamentals
형변환 (::) 관련 문의
안녕하세요!형변환 관련 문의드리고자 합니다.::text 등 더블콜론 활용한 기능이 매우 유용하다 말씀주셨는데 ::text의 경우 to_char로 작성했을 때 대비 어떤 이점 또는 차이가 있는지 궁금합니다.감사합니다.to_char(hiredate, 'yyyy-mm-dd')vsto_timestamp(hiredate, 'yyyy-mm-dd')::text
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
3-7 리텐션 SQL 쿼리 작성하기 연습 (Weekly, Monthly)
리텐션 SQL 쿼리 작성하기, Weekly와 Monthly 쿼리를 작성한 부분을 게시판에 올립니다.-- Weekly 리텐션 작성하기. 마지막 부분 , analysis AS (SELECT diff_of_week, user_cnt, FIRST_VALUE(user_cnt) OVER (ORDER BY diff_of_week) AS first_user_cnt FROM (SELECT diff_of_week, COUNT(DISTINCT user_pseudo_id) AS user_cnt FROM first_date_and_diff GROUP BY 1)) SELECT diff_of_week, user_cnt, ROUND(SAFE_DIVIDE(user_cnt, first_user_cnt), 3) AS retention_week_rate FROM analysis ORDER BY 1;-- 월별 리텐션 계산 WITH base AS ( SELECT DISTINCT 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_date_and_diff AS ( SELECT *, DATE_DIFf(event_month, first_month, MONTH) AS diff_of_month FROM ( SELECT DISTINCT user_pseudo_id, DATE_TRUNC(MIN(event_date) OVER(PARTITION BY user_pseudo_id), MONTH) AS first_month, DATE_TRUNC(event_date, MONTH) AS event_month FROM base ) ), analysis AS ( SELECT diff_of_month, user_cnt, FIRST_VALUE(user_cnt) OVER(ORDER BY diff_of_month) AS first_user_cnt FROM ( SELECT diff_of_month, COUNT(DISTINCT user_pseudo_id) AS user_cnt FROM first_date_and_diff GROUP BY 1 ) ) SELECT diff_of_month, user_cnt, ROUND(SAFE_DIVIDE(user_cnt, first_user_cnt), 3) AS retention_month_rate FROM analysis
-
미해결5시간 완성 SQLD(2과목)
실습 데이터
실습을 해보고 싶은데 혹시 예시 데이터는 어디서 구할 수 있을까요?
-
해결됨(2024) 일주일만에 합격하는 정보처리기사 실기
SQL은 어떻게 정리해야할까요?
SQL 문제도 2문제 정도씩 꾸준히 나오는 거 같던데, 이 부분에 대해선 강의를 올리실 계획이신지 궁금합니다.
-
해결됨초보자를 위한 BigQuery(SQL) 입문
1-2. BigQuery환경 설정 오류
강의 내용을 똑같이 따라했는데 'basic.pokemon'에서 오류가 떠요ㅠㅠ 제가 놓친게 있을까요?
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
강의 자료 파일을 열 수 없습니다.
윈도우 사용자입니다. 첨부파일을 다운로드 받았는데, 압축파일 풀기를 하면 아래와 같이 오류 메시지가 나오는데요. 어떻게 해결하면 좋을까요?
-
해결됨처음하는 SQL과 데이터베이스(MySQL) 부트캠프 [입문부터 활용까지] (업데이트)
인덱스 관련 질문!
인덱스에 대해서 약간의 의문을 질문드립니다. 인덱스가 조회의 성능 향상을 위한다는 점은 이해가 갑니다만..특정한 인덱스의 이름을 설정하는 부분이 약간 헷갈립니다. 가령 std_id 라는 인덱스를 학번을 저장 하는 column에 만들었을 때를 예시로 들겠습니다. 제가 학번의 데이터를 조회 하는경우 자체 프로그램에서 std_id의 인덱스만을 쉽게 찾는다는 의미이며, 이름설정은 단순 사용자들의 이해를 편하게 하기 위함인지가 궁금합니당
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
퍼널별 유저들의 새로운 세션 시작 횟수의 총합 _ 윈도우 함수 마지막 문제 응용
안녕하세요. 저는 이번에 마지막 문제를 응용해서, 퍼널별로 유저들의 새로운 세션 시작 횟수의 총합을 계산해보았습니다.[결과 그래프]새로운 세션 시작 기준: 이전 세션 시간 대비 20초 이상이 지나면, 새로운 세션을 활성화했다고 가정 (강의 내용과 동일)첫번째 강의에서 배운, UNNEST 문법과 PIVOT 을 하는 방법을 활용해서, event_params에 있는 firebase_screen의 string_value 값을 새로운 열인 firebase_screen 이라고 만듭니다. 전체 데이터를 조회하면, 쿼리 비용이 많이 들기 때문에, where 조건 절로 값을 작게 명시해줍니다.WITH base AS ( SELECT event_date, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_timestamp, event_name, user_pseudo_id, MAX(IF(ep.key = 'firebase_screen', ep.value.string_value, NULL)) AS firebase_screen FROM advanced.app_logs CROSS JOIN UNNEST(event_params) AS ep WHERE event_date = '2022-08-18' AND user_pseudo_id = '5464646449.4088767327' GROUP BY ALL )LAG() 함수를 사용하여, 이전 날짜 값을 가져옵니다. 이 때, 퍼널별로 구해야하기 때문에, PARTITION BY에 firebase_screen 을 써줍니다. 그 후, DATETIMEDIFF 함수를 사용해서, 현재값과 이전값의 차이를 계산합니다.WITH base AS ( SELECT event_date, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_timestamp, event_name, user_pseudo_id, MAX(IF(ep.key = 'firebase_screen', ep.value.string_value, NULL)) AS firebase_screen FROM advanced.app_logs CROSS JOIN UNNEST(event_params) AS ep WHERE event_date = '2022-08-18' AND user_pseudo_id = '5464646449.4088767327' GROUP BY ALL ), diff_funnel_time AS ( SELECT *, DATETIME_DIFF(event_timestamp, prev_event_timestamp, SECOND) AS second_diff FROM ( SELECT *, LAG(event_timestamp, 1) OVER(PARTITION BY firebase_screen ORDER BY event_timestamp) AS prev_event_timestamp FROM base ) ) SELECT * FROM diff_funnel_time3. ROW_NUMBER() 함수를 사용해서, 퍼널별로 순서를 매깁니다. 그 후, second_diff 의 값이 NULL인 경우는 해당 퍼널의 첫 시작 위치를 가리키므로 1을 넣어주고, rn > 1이고 second_diff >= 20인 경우는 1을 넣어줍니다. 이 때 funnel_per_session_start 컬럼은 퍼널별로 새로운 세션이 시작했는지 여부를 가리킵니다. , funnel_start AS ( SELECT *, CASE WHEN second_diff IS NULL THEN 1 WHEN rn > 1 AND second_diff >= 20 THEN 1 ELSE 0 END AS funnel_per_session_start FROM ( SELECT *, ROW_NUMBER() OVER(PARTITION BY firebase_screen ORDER BY event_timestamp) AS rn FROM diff_funnel_time ) )이제, 퍼널별로 세션 시작 여부를 SUM()하고, GROUP BY를 해줍니다.SELECT firebase_screen, SUM(funnel_per_session_start) AS funnel_per_session_start_cnt FROM funnel_start GROUP BY ALL ORDER BY 2 DESC;WHERE 조건절을 주석처리하고, 전체 데이터에 대해서, 집계해봅니다. WITH base AS ( SELECT event_date, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_timestamp, event_name, user_pseudo_id, MAX(IF(ep.key = 'firebase_screen', ep.value.string_value, NULL)) AS firebase_screen FROM advanced.app_logs CROSS JOIN UNNEST(event_params) AS ep -- WHERE -- event_date = '2022-08-18' -- AND user_pseudo_id = '5464646449.4088767327' GROUP BY ALL ), diff_funnel_time AS ( SELECT *, DATETIME_DIFF(event_timestamp, prev_event_timestamp, SECOND) AS second_diff FROM ( SELECT *, LAG(event_timestamp, 1) OVER(PARTITION BY firebase_screen ORDER BY event_timestamp) AS prev_event_timestamp FROM base ) ) , funnel_start AS ( SELECT *, CASE WHEN second_diff IS NULL THEN 1 WHEN rn > 1 AND second_diff >= 20 THEN 1 ELSE 0 END AS funnel_per_session_start FROM ( SELECT *, ROW_NUMBER() OVER(PARTITION BY firebase_screen ORDER BY event_timestamp) AS rn FROM diff_funnel_time ) ) SELECT firebase_screen, SUM(funnel_per_session_start) AS funnel_per_session_start_cnt FROM funnel_start GROUP BY ALL ORDER BY 2 DESC;
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
windows function default 값에 대하여 range between과 rows between의 차이
안녕하세요. 강의를 잘 듣고 있습니다.다름이 아니라, 연습문제를 모두 풀고 나서 윈도우함수 강의를 듣는 과정에서, default에 대해 궁금한 점이 생겼습니다. 정확히, 계산을 해야할 경우, 중복된 데이터가 있는 경우를 고려해서, ROWS BETWEEN UNBOUNDED PRECEDINIG AND CURRENT ROW 라고 프레임의 범위를 정확하게 명시를 하는 것이 좋을 것 같다. 라는 생각이 들었습니다.그 이유는 다음과 같습니다.강의에서 말씀해주신대로, 구글 빅쿼리는 default 값이 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 라고 되어있는데요,-- 4) -- 누적 쿼리: 과거의 시간(UNBOUNDED PRECEDING)부터 current row까지 SELECT *, SUM(query_cnt) OVER(PARTITION BY user ORDER BY query_date) AS cumulative_sum SUM(query_cnt) OVER(PARTITION BY user ORDER BY query_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cumulative_sum2 FROM ( SELECT query_date, team, user, COUNT(user) AS query_cnt FROM advanced.query_logs GROUP BY ALL ) -- QUALIFY cumulative_sum != cumulative_sum2 ORDER BY user, query_date문득, default값이 RANGE BETWEEN UNBOUND PRECEDING AND CURRENT ROW 라면, 왜 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 와 같은 값을 가질까? 다른 값을 가지는 경우도 있지 않을까? 하는 의문이 들었습니다.예제에서는, GROUP BY ALL을 했기 때문에, 중복 데이터가 있어도, query_cnt로 집계가 된 상태에서, 윈도우 함수를 실행하다보니, QUALIFY로 조건절 검증을 수행해도, != 를 만족하는 데이터가 없었던 것 같았습니다.그래서, 1번 예제와 4번 예제를 결합해서, 다음과 같이 검증을 수행해보았습니다.-- INSERT INTO my_sess.query_logs (user, team, query_date) -- VALUES ('샘', 'Data Science', '2024-04-24'); SELECT *, -- 시간의 흐름에 따라, 일자별 유저가 실행한 누적 총 쿼리 수 SUM(total_query_cnt) OVER(PARTITION BY user ORDER BY query_date) AS cumulative_total_sum, SUM(total_query_cnt) OVER(PARTITION BY user ORDER BY query_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cumulative_total_sum2 FROM ( SELECT *, -- 사용자별 시간의 흐름에 따라 쿼리를 실행한 총 횟수: total_query_cnt COUNT(query_date) OVER(PARTITION BY user) AS total_query_cnt FROM my_sess.query_logs ) -- QUALIFY cumulative_total_sum != cumulative_total_sum2 ORDER BY user, query_date결과는 다음과 같습니다.중복데이터가 있을 경우, RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW는 다 합쳐서 하나로 집계해서 결과값을 내놓는 것으로 보입니다.QUALIFY 함수를 적용했을 때cumulative_total_sum = cumulative_total_sum2 인 경우데이터 중복이 없을 경우에는, 같은 값이 나옵니다.