いつもお世話になっております。
SQLの作成につまづいており、どなたかご教授いただきたいです。
詳細は以下になります。
<環境>
・クエリ実行環境:TresureData(ビッグデータ集計ツール)
・SQL:presto
<求めたいクエリ>
・ゲームのKPIを求めるクエリです。
・日毎の課金UUの累計を、プラットフォーム毎(iOS,Android)に求めます。
・具体例を示すと、次のような感じです。
date platform uu
2016-01-01 ios 100
2016-01-01 android 70
2016-01-02 ios 120 <- 前日からだんだん累計されていく
2016-01-02 android 130
<困っている点>
・window関数を使って、課金UUの累計を求めようとしています。
ただ、prestoだと、window関数で DISTINCTを使えないようです...。
window関数を代替して、どうにか求める方法はないでしょうか?
<実際のクエリ>
sql
1-- 日別プラットフォーム別に、課金したユーザの一覧を取る 2WITH sub1 AS 3( 4SELECT 5 TD_TIME_FORMAT(time,'yyyy-MM-dd','JST') AS date 6 ,{platform} 7 ,user_id 8FROM 9 kpi_table 10WHERE 11 --月初め〜月末まで取る 12 TD_TIME_RANGE( 13 time 14 ,TD_TIME_FORMAT({month_start},'yyyy-MM-dd 00:00:00','JST') 15 ,TD_TIME_FORMAT({month_last},'yyyy-MM-dd 23:59:59','JST') 16 ,'JST' 17 ) 18 --課金したユーザのみ 19 AND (purchase_amount > 0) 20GROUP BY 21 TD_TIME_FORMAT(time,'yyyy-MM-dd','JST') 22 ,{platform} 23 ,user_id 24ORDER BY 25 TD_TIME_FORMAT(time,'yyyy-MM-dd','JST') ASC 26 ,{platform} ASC 27 ,user_id 28) 29-- 集計 30SELECT 31 date 32 ,{platform} 33 -- Window関数で DISTINCTは未実装のため、ここでエラーになる 34 ,COUNT(DISTINCT user_id) OVER(PARTITION BY {platform} ORDER BY date ASC) AS charging_uu 35FROM 36 sub1 37ORDER BY 38 date 39 ,{platform} 40--...(実際のクエリは、この後も処理が続きます...)
<補足>
・クエリ中の{}で囲っている箇所は、ツールを使って動的に値が入ります。
・代替案として、クエリを日別に生成して(ex 7/1までのSQL、7/2までのSQL、、、)
順にクエリを実行する方法も考えました。
ただ、パフォーマンスに影響する都合上、
クエリの実行は1回に抑えたく、この代替案は取れません。
・クエリはjupyter上から実行しています。
途中まで計算した段階で
pandas-tdライブラリのDataFrameクラスを使い、
jupyter上で集計を行うのもありかと思います。
ただ、jupyterを実行するマシンは、そこまでスペックが高くなく、
jupyter上で集計しようとするとパフォーマンスがでないと思います。
できれば、クエリ上で集計を全て行いたいです。
以上になります。
SQLに詳しい方、ビックデータに詳しい方etc...
ご教授いただけますと幸いですb
20160728追記
- 一応、window関数とWHERE句を使って書くことはできました(以下になります)。
- まだ冗長なクエリなので、何かスマートな書き方をご存知な方がいれば、教えていただけますと幸いです...b
sql
1-- 日別プラットフォーム別に、課金したユーザの一覧を取る 2WITH sub1 AS 3( 4SELECT 5 TD_TIME_FORMAT(time,'yyyy-MM-dd','JST') AS date 6 ,{platform} 7 ,user_id 8FROM 9 kpi_table 10WHERE 11 --月初め〜月末まで取る 12 TD_TIME_RANGE( 13 time 14 ,TD_TIME_FORMAT({month_start},'yyyy-MM-dd 00:00:00','JST') 15 ,TD_TIME_FORMAT({month_last},'yyyy-MM-dd 23:59:59','JST') 16 ,'JST' 17 ) 18 --課金したユーザのみ 19 AND (purchase_amount > 0) 20GROUP BY 21 TD_TIME_FORMAT(time,'yyyy-MM-dd','JST') 22 ,{platform} 23 ,user_id 24ORDER BY 25 TD_TIME_FORMAT(time,'yyyy-MM-dd','JST') ASC 26 ,{platform} ASC 27 ,user_id 28) 29-- ユーザ毎のログイン日を集計 30, sub2 AS 31( 32SELECT 33 date 34 ,{platform} 35 ,user_id 36 ,COUNT(user_id) OVER (PARTITION BY {platform}, user_id ORDER BY date) AS login_count 37FROM 38 sub1 39ORDER BY 40 date ASC 41 ,{platform} ASC 42 ,user_id 43) 44-- 全ユーザのログイン日を集計 45, sub3 AS 46( 47SELECT 48 date 49 ,{platform} 50 ,COUNT(user_id) OVER (PARTITION BY platform ORDER BY date) user_num 51FROM 52 sub2 53--最初にログインした日以外のデータは排除 54WHERE 55 login_count = 1 56ORDER BY 57 date ASC 58 ,{platform} ASC 59) 60-- データを日別 * プラットフォーム別に絞る 61SELECT 62 date 63 ,{platform} 64 MAX(user_num) AS user_num 65FROM 66 sub3 67GROUP BY 68 date 69 ,{platform} 70ORDER BY 71 date ASC 72 ,{platform} ASC
回答1件
あなたの回答
tips
プレビュー