MySQL 5.6 時間區間 復購率 查詢筆記
阿新 • • 發佈:2022-05-06
如果有的選,我也不想在不支援窗體函式的資料庫上這麼拐彎抹角的寫sql。
這個需求的本質是 多維度切分不同的訂單和使用者組,然後組內排序然後比較相鄰行的日期。用窗體函式會非常的舒服,可是沒有如果。
這是最終要匯出的報表
# 使用者下單金額 DROP VIEW IF EXISTS `v_user_kedanjia`; CREATE VIEW v_user_kedanjia AS SELECT ui.user_id, IFNULL( COUNT(DISTINCT om.internal_pay_id), 0) order_num, IFNULL( SUM( om.order_amt ), 0.00 ) order_amt_sum FROM ty_user_info ui LEFT JOIN ty_order_master om ON ui.user_id = om.user_info_id AND om.pay_time IS NOT NULL AND om.order_status != 3 AND om.is_delete = 0 WHERE ui.is_delete = 0 GROUP BY ui.user_id; # 不同價格分組使用者 DROP VIEW IF EXISTS `v_user_kedanjia_2`; CREATE VIEW v_user_kedanjia_2 AS SELECT 1 `num`, '0~1000' `order_amt`, user_id FROM v_user_kedanjia WHERE order_amt_sum >= 0 AND order_amt_sum <= 1000 UNION SELECT 2 `num`, '1000~2000' `order_amt`, user_id FROM v_user_kedanjia WHERE order_amt_sum > 1000 AND order_amt_sum <= 2000 UNION SELECT 3 `num`, '2000~3000' `order_amt`, user_id FROM v_user_kedanjia WHERE order_amt_sum > 2000 AND order_amt_sum <= 3000 UNION SELECT 4 `num`, '3000~5000' `order_amt`, user_id FROM v_user_kedanjia WHERE order_amt_sum > 3000 AND order_amt_sum <= 5000 UNION SELECT 5 `num`, '5000~10000' `order_amt`, user_id FROM v_user_kedanjia WHERE order_amt_sum > 5000 AND order_amt_sum <= 10000 UNION SELECT 6 `num`, '10000以上' `order_amt`, user_id FROM v_user_kedanjia WHERE order_amt_sum > 10000; # 復購率 # 建檢視是因為必須先通過 user_info_id, order_date 排序否則 rownum 會亂掉 DROP VIEW IF EXISTS `v_user_kedanjia_fugoulv_1`; CREATE VIEW v_user_kedanjia_fugoulv_1 AS (SELECT 1 'num', user_info_id, DATE_FORMAT(creator_time, '%Y-%m-%d') order_date, order_num FROM ty_order_master WHERE pay_time IS NOT NULL AND order_status != 3 AND order_amt >= 0 AND order_amt <= 1000 ORDER BY user_info_id, order_date) UNION (SELECT 2 'num', user_info_id, DATE_FORMAT(creator_time, '%Y-%m-%d') order_date, order_num FROM ty_order_master WHERE pay_time IS NOT NULL AND order_status != 3 AND order_amt > 1000 AND order_amt <= 2000 ORDER BY user_info_id, order_date) UNION (SELECT 3 'num', user_info_id, DATE_FORMAT(creator_time, '%Y-%m-%d') order_date, order_num FROM ty_order_master WHERE pay_time IS NOT NULL AND order_status != 3 AND order_amt > 2000 AND order_amt <= 3000 ORDER BY user_info_id, order_date) UNION (SELECT 4 'num', user_info_id, DATE_FORMAT(creator_time, '%Y-%m-%d') order_date, order_num FROM ty_order_master WHERE pay_time IS NOT NULL AND order_status != 3 AND order_amt > 3000 AND order_amt <= 5000 ORDER BY user_info_id, order_date) UNION (SELECT 6 'num', user_info_id, DATE_FORMAT(creator_time, '%Y-%m-%d') order_date, order_num FROM ty_order_master WHERE pay_time IS NOT NULL AND order_status != 3 AND order_amt > 10000 ORDER BY user_info_id, order_date); # rownum 為每一條資料重新編號 SELECT (@index1:=@index1+1) rownum, order_date, user_info_id, order_num FROM v_user_kedanjia_fugoulv_1,(SELECT @index1:=0) r WHERE user_info_id = 4453; SELECT TIMESTAMPDIFF(DAY,'2021-11-01','2022-04-10'); # 每一條資料重新編號 # 比較相鄰的兩條資料 判斷時間間隔是否為N天 SELECT DISTINCT r1.user_info_id, r1.order_num, r2.order_num FROM (SELECT (@index1:=@index1+1) rownum, order_date, user_info_id, order_num, num FROM v_user_kedanjia_fugoulv_1,(SELECT @index1:=0) r) r1 LEFT JOIN (SELECT (@index2:=@index2+1) rownum, order_date, user_info_id, order_num, num FROM v_user_kedanjia_fugoulv_1,(SELECT @index2:=0) r) r2 ON r1.user_info_id = r2.user_info_id AND r1.rownum+1 = r2.rownum WHERE r1.num = 6 AND TIMESTAMPDIFF(DAY,r1.order_date,r2.order_date) >= 0 AND TIMESTAMPDIFF(DAY,r1.order_date,r2.order_date) <= 100; # 客單價 SELECT t2.order_amt, COUNT(t2.user_id) `使用者數(包含未下單的使用者)`, COUNT(t2.user_id) / (SELECT COUNT(user_id) FROM v_user_kedanjia) `佔比`, COUNT(CASE WHEN t1.order_num = 1 THEN t1.user_id END) `首單使用者數`, COUNT(CASE WHEN t1.order_num > 1 THEN t1.user_id END) `非首單使用者數`, (SELECT COUNT(DISTINCT r1.user_info_id) FROM (SELECT (@index1:=@index1+1) rownum, order_date, user_info_id, order_num, num FROM v_user_kedanjia_fugoulv_1,(SELECT @index1:=0) r) r1 LEFT JOIN (SELECT (@index2:=@index2+1) rownum, order_date, user_info_id, order_num, num FROM v_user_kedanjia_fugoulv_1,(SELECT @index2:=0) r) r2 ON r1.user_info_id = r2.user_info_id AND r1.rownum+1 = r2.rownum WHERE r1.num = t2.num AND TIMESTAMPDIFF(DAY,r1.order_date,r2.order_date) >= 0 AND TIMESTAMPDIFF(DAY,r1.order_date,r2.order_date) <= 7) `1-7天覆購率`, (SELECT COUNT(DISTINCT r1.user_info_id) FROM (SELECT (@index1:=@index1+1) rownum, order_date, user_info_id, order_num, num FROM v_user_kedanjia_fugoulv_1,(SELECT @index1:=0) r) r1 LEFT JOIN (SELECT (@index2:=@index2+1) rownum, order_date, user_info_id, order_num, num FROM v_user_kedanjia_fugoulv_1,(SELECT @index2:=0) r) r2 ON r1.user_info_id = r2.user_info_id AND r1.rownum+1 = r2.rownum WHERE r1.num = t2.num AND TIMESTAMPDIFF(DAY,r1.order_date,r2.order_date) >= 8 AND TIMESTAMPDIFF(DAY,r1.order_date,r2.order_date) <= 15) `8-15天覆購率`, (SELECT COUNT(DISTINCT r1.user_info_id) FROM (SELECT (@index1:=@index1+1) rownum, order_date, user_info_id, order_num, num FROM v_user_kedanjia_fugoulv_1,(SELECT @index1:=0) r) r1 LEFT JOIN (SELECT (@index2:=@index2+1) rownum, order_date, user_info_id, order_num, num FROM v_user_kedanjia_fugoulv_1,(SELECT @index2:=0) r) r2 ON r1.user_info_id = r2.user_info_id AND r1.rownum+1 = r2.rownum WHERE r1.num = t2.num AND TIMESTAMPDIFF(DAY,r1.order_date,r2.order_date) >= 16 AND TIMESTAMPDIFF(DAY,r1.order_date,r2.order_date) <= 26) `16-23天覆購率`, (SELECT COUNT(DISTINCT r1.user_info_id) FROM (SELECT (@index1:=@index1+1) rownum, order_date, user_info_id, order_num, num FROM v_user_kedanjia_fugoulv_1,(SELECT @index1:=0) r) r1 LEFT JOIN (SELECT (@index2:=@index2+1) rownum, order_date, user_info_id, order_num, num FROM v_user_kedanjia_fugoulv_1,(SELECT @index2:=0) r) r2 ON r1.user_info_id = r2.user_info_id AND r1.rownum+1 = r2.rownum WHERE r1.num = t2.num AND TIMESTAMPDIFF(DAY,r1.order_date,r2.order_date) >= 24 AND TIMESTAMPDIFF(DAY,r1.order_date,r2.order_date) <= 30) `24-30天覆購率`, (SELECT COUNT(DISTINCT r1.user_info_id) FROM (SELECT (@index1:=@index1+1) rownum, order_date, user_info_id, order_num, num FROM v_user_kedanjia_fugoulv_1,(SELECT @index1:=0) r) r1 LEFT JOIN (SELECT (@index2:=@index2+1) rownum, order_date, user_info_id, order_num, num FROM v_user_kedanjia_fugoulv_1,(SELECT @index2:=0) r) r2 ON r1.user_info_id = r2.user_info_id AND r1.rownum+1 = r2.rownum WHERE r1.num = t2.num AND TIMESTAMPDIFF(DAY,r1.order_date,r2.order_date) >= 31 AND TIMESTAMPDIFF(DAY,r1.order_date,r2.order_date) <= 60) `31-60天覆購率` FROM v_user_kedanjia t1 LEFT JOIN v_user_kedanjia_2 t2 ON t1.user_id = t2.user_id GROUP BY t2.num ORDER BY t2.num;
效果截圖