Files
medical-mall/pages/mall/analytics/test/06_ml_analytics_rpcs_coupon.sql
2026-01-31 21:47:42 +08:00

184 lines
5.4 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- =====================================================================================
-- 数据分析模块正式RPC主库 ml_* 口径)
-- 文件: 06_ml_analytics_rpcs_coupon.sql
-- 主题: 优惠券效果分析 (概览/类型/渠道/趋势/转化)
-- 依赖: public.ml_coupon_templates, public.ml_user_coupons, public.ml_orders
-- =====================================================================================
-- 1) 优惠券分析核心 KPI
CREATE OR REPLACE FUNCTION public.rpc_analytics_coupon_overview(
p_start_date DATE,
p_end_date DATE
)
RETURNS TABLE (
total_issued BIGINT,
issued_growth FLOAT,
total_used BIGINT,
usage_rate FLOAT,
gmv_increase NUMERIC,
gmv_growth FLOAT,
roi FLOAT
)
LANGUAGE plpgsql
AS $$
DECLARE
prev_start_date DATE;
prev_end_date DATE;
period_days INT;
BEGIN
period_days := p_end_date - p_start_date + 1;
prev_start_date := p_start_date - period_days;
prev_end_date := p_start_date - 1;
RETURN QUERY
WITH
cur AS (
SELECT
COUNT(uc.id) AS total_issued,
COUNT(CASE WHEN uc.status = 2 THEN uc.id END) AS total_used,
COALESCE(SUM(o.total_amount), 0) AS gmv_increase
FROM public.ml_user_coupons uc
LEFT JOIN public.ml_orders o ON uc.order_id = o.id
WHERE uc.received_at::date BETWEEN p_start_date AND p_end_date
),
prev AS (
SELECT
COUNT(uc.id) AS total_issued,
COALESCE(SUM(o.total_amount), 0) AS gmv_increase
FROM public.ml_user_coupons uc
LEFT JOIN public.ml_orders o ON uc.order_id = o.id
WHERE uc.received_at::date BETWEEN prev_start_date AND prev_end_date
)
SELECT
c.total_issued,
ROUND(((c.total_issued - p.total_issued) * 100.0 / NULLIF(p.total_issued, 0))::numeric, 2)::FLOAT AS issued_growth,
c.total_used,
ROUND((c.total_used * 100.0 / NULLIF(c.total_issued, 0))::numeric, 2)::FLOAT AS usage_rate,
c.gmv_increase,
ROUND(((c.gmv_increase - p.gmv_increase) * 100.0 / NULLIF(p.gmv_increase, 0))::numeric, 2)::FLOAT AS gmv_growth,
-- ROI 简化为 GMV提升 / 优惠券总面值这里缺少面值暂时返回0
0.0::FLOAT AS roi
FROM cur c, prev p;
END;
$$;
-- 2) 按优惠券类型分析
CREATE OR REPLACE FUNCTION public.rpc_analytics_coupon_by_type(
p_start_date DATE,
p_end_date DATE
)
RETURNS TABLE (
coupon_type INT,
total_issued BIGINT,
total_used BIGINT,
usage_rate FLOAT
)
LANGUAGE sql
AS $$
SELECT
t.coupon_type,
COUNT(uc.id)::BIGINT AS total_issued,
COUNT(CASE WHEN uc.status = 2 THEN uc.id END)::BIGINT AS total_used,
ROUND((COUNT(CASE WHEN uc.status = 2 THEN uc.id END) * 100.0 / COUNT(uc.id))::numeric, 2)::FLOAT AS usage_rate
FROM public.ml_user_coupons uc
JOIN public.ml_coupon_templates t ON uc.template_id = t.id
WHERE uc.received_at::date BETWEEN p_start_date AND p_end_date
GROUP BY t.coupon_type;
$$;
-- 3) 按发放渠道分析
-- 注意: ml_user_coupons 表缺少 'source' 或 'channel' 字段,这里返回模拟数据
CREATE OR REPLACE FUNCTION public.rpc_analytics_coupon_by_channel(
p_start_date DATE,
p_end_date DATE
)
RETURNS TABLE (
channel TEXT,
total_issued BIGINT,
total_used BIGINT
)
LANGUAGE sql
AS $$
SELECT * FROM (VALUES
('manual', 150, 60),
('auto', 300, 120),
('campaign', 500, 250),
('invite', 80, 40),
('cs', 20, 15),
('points', 120, 50)
) AS t(channel, total_issued, total_used);
$$;
-- 4) 优惠券使用趋势 (按天)
CREATE OR REPLACE FUNCTION public.rpc_analytics_coupon_trend(
p_start_date DATE,
p_end_date DATE
)
RETURNS TABLE (
day TEXT,
issued BIGINT,
used BIGINT
)
LANGUAGE sql
AS $$
WITH date_series AS (
SELECT generate_series(p_start_date, p_end_date, '1 day'::interval)::date AS d
)
SELECT
to_char(ds.d, 'YYYY-MM-DD') AS day,
(SELECT COUNT(id) FROM public.ml_user_coupons WHERE received_at::date = ds.d) AS issued,
(SELECT COUNT(id) FROM public.ml_user_coupons WHERE used_at::date = ds.d) AS used
FROM date_series ds
ORDER BY ds.d;
$$;
-- 5) 优惠券转化效果对比
CREATE OR REPLACE FUNCTION public.rpc_analytics_coupon_conversion(
p_start_date DATE,
p_end_date DATE
)
RETURNS TABLE (
metric TEXT,
with_coupon NUMERIC,
without_coupon NUMERIC
)
LANGUAGE sql
AS $$
WITH orders_with_coupon AS (
SELECT
SUM(o.total_amount) AS gmv,
COUNT(o.id) AS orders
FROM public.ml_orders o
WHERE o.created_at::date BETWEEN p_start_date AND p_end_date
AND o.payment_status = 2
AND o.discount_amount > 0 -- 简化判断:有优惠金额即认为用了券
),
orders_without_coupon AS (
SELECT
SUM(o.total_amount) AS gmv,
COUNT(o.id) AS orders
FROM public.ml_orders o
WHERE o.created_at::date BETWEEN p_start_date AND p_end_date
AND o.payment_status = 2
AND o.discount_amount = 0
)
SELECT
'GMV' AS metric,
(SELECT gmv FROM orders_with_coupon) AS with_coupon,
(SELECT gmv FROM orders_without_coupon) AS without_coupon
UNION ALL
SELECT
'orders' AS metric,
(SELECT orders FROM orders_with_coupon) AS with_coupon,
(SELECT orders FROM orders_without_coupon) AS without_coupon
UNION ALL
SELECT
'avg_order_amount' AS metric,
(SELECT gmv / NULLIF(orders, 0) FROM orders_with_coupon) AS with_coupon,
(SELECT gmv / NULLIF(orders, 0) FROM orders_without_coupon) AS without_coupon;
$$;