数据分析ui补充完善,接入数据库
This commit is contained in:
176
pages/mall/analytics/test/02_ml_analytics_rpcs_sales.sql
Normal file
176
pages/mall/analytics/test/02_ml_analytics_rpcs_sales.sql
Normal file
@@ -0,0 +1,176 @@
|
||||
-- =====================================================================================
|
||||
-- 数据分析模块(正式RPC,主库 ml_* 口径)
|
||||
-- 文件: 02_ml_analytics_rpcs_sales.sql
|
||||
-- 主题: 仪表盘/销售报表(KPI/趋势/TOP)
|
||||
-- 口径约定:
|
||||
-- - GMV: paid_amount 汇总(若为 0 则用 total_amount 兜底)
|
||||
-- - 订单量: ml_orders created_at 期间内订单数(可按需要切换为支付订单数)
|
||||
-- - 支付用户数: payment_status=2 的 distinct user_id
|
||||
-- - 活跃用户数: ml_browse_history created_at 期间内 distinct user_id(弱口径)
|
||||
-- - 转化率(A): 支付用户数 / 活跃用户数(*100)
|
||||
-- =====================================================================================
|
||||
|
||||
-- 1) 销售核心 KPI(含上期对比)
|
||||
CREATE OR REPLACE FUNCTION public.rpc_analytics_sales_kpis(
|
||||
p_start_date DATE,
|
||||
p_end_date DATE
|
||||
)
|
||||
RETURNS TABLE (
|
||||
gmv NUMERIC,
|
||||
gmv_growth FLOAT,
|
||||
orders BIGINT,
|
||||
order_growth FLOAT,
|
||||
conversion_rate FLOAT,
|
||||
conversion_growth FLOAT,
|
||||
avg_order_amount NUMERIC,
|
||||
avg_order_growth 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
|
||||
COALESCE(
|
||||
SUM(CASE WHEN o.payment_status = 2 THEN COALESCE(NULLIF(o.paid_amount, 0), o.total_amount) ELSE 0 END),
|
||||
0
|
||||
) AS gmv,
|
||||
COUNT(*)::BIGINT AS orders,
|
||||
COUNT(DISTINCT CASE WHEN o.payment_status = 2 THEN o.user_id END)::BIGINT AS paid_users,
|
||||
(SELECT COUNT(DISTINCT bh.user_id) FROM public.ml_browse_history bh WHERE bh.created_at::DATE BETWEEN p_start_date AND p_end_date)::BIGINT AS active_users
|
||||
FROM public.ml_orders o
|
||||
WHERE o.created_at::DATE BETWEEN p_start_date AND p_end_date
|
||||
),
|
||||
-- 上一周期
|
||||
prev AS (
|
||||
SELECT
|
||||
COALESCE(
|
||||
SUM(CASE WHEN o.payment_status = 2 THEN COALESCE(NULLIF(o.paid_amount, 0), o.total_amount) ELSE 0 END),
|
||||
0
|
||||
) AS gmv,
|
||||
COUNT(*)::BIGINT AS orders,
|
||||
COUNT(DISTINCT CASE WHEN o.payment_status = 2 THEN o.user_id END)::BIGINT AS paid_users,
|
||||
(SELECT COUNT(DISTINCT bh.user_id) FROM public.ml_browse_history bh WHERE bh.created_at::DATE BETWEEN prev_start_date AND prev_end_date)::BIGINT AS active_users
|
||||
FROM public.ml_orders o
|
||||
WHERE o.created_at::DATE BETWEEN prev_start_date AND prev_end_date
|
||||
),
|
||||
calc AS (
|
||||
SELECT
|
||||
cur.gmv AS gmv,
|
||||
cur.orders AS orders,
|
||||
CASE WHEN cur.active_users > 0 THEN (cur.paid_users::NUMERIC / cur.active_users::NUMERIC) * 100 ELSE 0 END AS conversion_rate,
|
||||
CASE WHEN cur.orders > 0 THEN cur.gmv / cur.orders ELSE 0 END AS avg_order_amount,
|
||||
|
||||
prev.gmv AS prev_gmv,
|
||||
prev.orders AS prev_orders,
|
||||
CASE WHEN prev.active_users > 0 THEN (prev.paid_users::NUMERIC / prev.active_users::NUMERIC) * 100 ELSE 0 END AS prev_conversion_rate,
|
||||
CASE WHEN prev.orders > 0 THEN prev.gmv / prev.orders ELSE 0 END AS prev_avg_order_amount
|
||||
FROM cur, prev
|
||||
)
|
||||
SELECT
|
||||
ROUND(calc.gmv, 2) AS gmv,
|
||||
ROUND(((calc.gmv - calc.prev_gmv) * 100.0 / NULLIF(calc.prev_gmv, 0))::numeric, 2)::FLOAT AS gmv_growth,
|
||||
calc.orders,
|
||||
ROUND(((calc.orders - calc.prev_orders) * 100.0 / NULLIF(calc.prev_orders, 0))::numeric, 2)::FLOAT AS order_growth,
|
||||
ROUND(calc.conversion_rate::numeric, 2)::FLOAT AS conversion_rate,
|
||||
ROUND((calc.conversion_rate - calc.prev_conversion_rate)::numeric, 2)::FLOAT AS conversion_growth,
|
||||
ROUND(calc.avg_order_amount, 2) AS avg_order_amount,
|
||||
ROUND(((calc.avg_order_amount - calc.prev_avg_order_amount) * 100.0 / NULLIF(calc.prev_avg_order_amount, 0))::numeric, 2)::FLOAT AS avg_order_growth
|
||||
FROM calc;
|
||||
END;
|
||||
$$;
|
||||
|
||||
|
||||
-- 2) 销售趋势(日维度:GMV + 订单数)
|
||||
CREATE OR REPLACE FUNCTION public.rpc_analytics_sales_trend(
|
||||
p_start_date DATE,
|
||||
p_end_date DATE
|
||||
)
|
||||
RETURNS TABLE (
|
||||
date DATE,
|
||||
gmv NUMERIC,
|
||||
orders BIGINT
|
||||
)
|
||||
LANGUAGE sql
|
||||
AS $$
|
||||
WITH date_series AS (
|
||||
SELECT generate_series(p_start_date, p_end_date, '1 day'::interval)::DATE AS date
|
||||
)
|
||||
SELECT
|
||||
ds.date,
|
||||
COALESCE(
|
||||
SUM(CASE WHEN o.payment_status = 2 THEN COALESCE(NULLIF(o.paid_amount, 0), o.total_amount) ELSE 0 END),
|
||||
0
|
||||
) AS gmv,
|
||||
COUNT(o.id)::BIGINT AS orders
|
||||
FROM date_series ds
|
||||
LEFT JOIN public.ml_orders o
|
||||
ON o.created_at::DATE = ds.date
|
||||
GROUP BY ds.date
|
||||
ORDER BY ds.date;
|
||||
$$;
|
||||
|
||||
|
||||
-- 3) 热销商品 TOP(按销量:sum(quantity))
|
||||
CREATE OR REPLACE FUNCTION public.rpc_analytics_top_products(
|
||||
p_start_date DATE,
|
||||
p_end_date DATE,
|
||||
p_limit INT DEFAULT 50
|
||||
)
|
||||
RETURNS TABLE (
|
||||
id UUID,
|
||||
name TEXT,
|
||||
sales BIGINT
|
||||
)
|
||||
LANGUAGE sql
|
||||
AS $$
|
||||
SELECT
|
||||
p.id,
|
||||
p.name::TEXT,
|
||||
COALESCE(SUM(oi.quantity), 0)::BIGINT AS sales
|
||||
FROM public.ml_order_items oi
|
||||
JOIN public.ml_orders o ON o.id = oi.order_id
|
||||
JOIN public.ml_products p ON p.id = oi.product_id
|
||||
WHERE o.created_at::DATE BETWEEN p_start_date AND p_end_date
|
||||
AND o.payment_status = 2
|
||||
GROUP BY p.id, p.name
|
||||
ORDER BY sales DESC
|
||||
LIMIT p_limit;
|
||||
$$;
|
||||
|
||||
|
||||
-- 4) 商家排行 TOP(按 GMV:支付 GMV)
|
||||
CREATE OR REPLACE FUNCTION public.rpc_analytics_top_merchants(
|
||||
p_start_date DATE,
|
||||
p_end_date DATE,
|
||||
p_limit INT DEFAULT 50
|
||||
)
|
||||
RETURNS TABLE (
|
||||
id UUID,
|
||||
name TEXT,
|
||||
sales NUMERIC
|
||||
)
|
||||
LANGUAGE sql
|
||||
AS $$
|
||||
SELECT
|
||||
m.id,
|
||||
COALESCE(NULLIF(m.username, ''), '未知商家')::TEXT AS name,
|
||||
COALESCE(SUM(COALESCE(NULLIF(o.paid_amount, 0), o.total_amount)), 0) AS sales
|
||||
FROM public.ml_orders o
|
||||
JOIN public.ak_users m ON m.id = o.merchant_id
|
||||
WHERE o.created_at::DATE BETWEEN p_start_date AND p_end_date
|
||||
AND o.payment_status = 2
|
||||
GROUP BY m.id, m.username
|
||||
ORDER BY sales DESC
|
||||
LIMIT p_limit;
|
||||
$$;
|
||||
Reference in New Issue
Block a user