数据分析ui补充完善,接入数据库

This commit is contained in:
comlibmb
2026-01-31 21:47:42 +08:00
parent 8f181b2b6a
commit 6716398175
71 changed files with 6501 additions and 10593 deletions

View 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;
$$;