-- ===================================================================================== -- 数据分析模块(正式RPC,主库 ml_* 口径) -- 文件: 07_ml_analytics_rpcs_delivery.sql -- 主题: 配送效率分析 (趋势/费用/配送员排行) -- 依赖: public.ml_delivery_tasks, public.ml_delivery_drivers -- 口径约定: -- - 完成配送:ml_delivery_tasks.status = 5 -- - 配送时长:delivered_at - assigned_at(分钟) -- - avg_fee:delivery_fee 平均 -- 弃用 -- ===================================================================================== -- 1) 配送效率日趋势 -- 返回字段需匹配前端 delivery-analysis.uvue:day / completed_orders / avg_delivery_minutes / avg_fee / total_fee CREATE OR REPLACE FUNCTION public.rpc_delivery_efficiency_daily( p_start TIMESTAMPTZ, p_end TIMESTAMPTZ ) RETURNS TABLE ( day TEXT, completed_orders BIGINT, avg_delivery_minutes NUMERIC, avg_fee NUMERIC, total_fee NUMERIC ) LANGUAGE sql AS $$ WITH date_series AS ( SELECT generate_series(date_trunc('day', p_start), date_trunc('day', p_end), interval '1 day')::date AS d ), tasks AS ( SELECT assigned_at::date AS d, EXTRACT(EPOCH FROM (delivered_at - assigned_at)) / 60.0 AS minutes, delivery_fee FROM public.ml_delivery_tasks WHERE status = 5 AND assigned_at IS NOT NULL AND delivered_at IS NOT NULL AND assigned_at >= p_start AND assigned_at < (p_end + interval '1 second') ) SELECT to_char(ds.d, 'YYYY-MM-DD') AS day, COUNT(t.minutes)::bigint AS completed_orders, ROUND(COALESCE(AVG(t.minutes), 0)::numeric, 2) AS avg_delivery_minutes, ROUND(COALESCE(AVG(t.delivery_fee), 0)::numeric, 2) AS avg_fee, ROUND(COALESCE(SUM(t.delivery_fee), 0)::numeric, 2) AS total_fee FROM date_series ds LEFT JOIN tasks t ON t.d = ds.d GROUP BY ds.d ORDER BY ds.d; $$; -- 2) 配送员效率排行 TOP -- 返回字段需匹配前端 delivery-analysis.uvue:driver_id / driver_name / orders / rating_avg CREATE OR REPLACE FUNCTION public.rpc_delivery_efficiency_top_drivers( p_start TIMESTAMPTZ, p_end TIMESTAMPTZ, p_limit INT DEFAULT 10 ) RETURNS TABLE ( driver_id TEXT, driver_name TEXT, orders BIGINT, rating_avg NUMERIC ) LANGUAGE sql AS $$ SELECT d.user_id::text AS driver_id, COALESCE(NULLIF(u.username, ''), d.real_name, '未知')::text AS driver_name, COUNT(t.id)::bigint AS orders, COALESCE(d.rating_avg, 0)::numeric AS rating_avg FROM public.ml_delivery_tasks t JOIN public.ml_delivery_drivers d ON d.id = t.driver_id LEFT JOIN public.ak_users u ON u.id = d.user_id WHERE t.status = 5 AND t.assigned_at IS NOT NULL AND t.assigned_at >= p_start AND t.assigned_at < (p_end + interval '1 second') GROUP BY d.user_id, u.username, d.real_name, d.rating_avg ORDER BY orders DESC LIMIT p_limit; $$;