1. 程式人生 > 其它 >MySQL 5.6 時間區間 復購率 查詢筆記

MySQL 5.6 時間區間 復購率 查詢筆記

如果有的選,我也不想在不支援窗體函式的資料庫上這麼拐彎抹角的寫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;

效果截圖