feat: 月度模式全面参数化 - 移除硬编码日期,前后端按月动态查询
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
-- ============================================================
|
||||
-- Phase 8: mv_store_risk_rating 参数化函数
|
||||
-- 替换普通表 mv_store_risk_rating(4月快照)为参数化函数
|
||||
-- 依赖: bill_fact, v_anomaly_bills
|
||||
-- ============================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION analytics.fn_store_risk_rating(p_month date)
|
||||
RETURNS TABLE (
|
||||
store_code text,
|
||||
store_name text,
|
||||
bill_count bigint,
|
||||
active_days bigint,
|
||||
received numeric,
|
||||
avg_daily_received numeric,
|
||||
avg_bill_value numeric,
|
||||
avg_guest_value numeric,
|
||||
discount_rate_pct numeric,
|
||||
theoretical_margin_pct numeric,
|
||||
member_bill_share_pct numeric,
|
||||
anomaly_rate_pct numeric,
|
||||
risk_level text,
|
||||
primary_issue text
|
||||
) AS $$
|
||||
WITH base AS (
|
||||
SELECT
|
||||
b.store_code,
|
||||
b.store_name,
|
||||
count(*) AS bill_count,
|
||||
count(DISTINCT b.closed_at::date) AS active_days,
|
||||
sum(b.received_total) AS received,
|
||||
round(sum(b.received_total) / NULLIF(count(DISTINCT b.closed_at::date), 0), 2) AS avg_daily_received,
|
||||
round(sum(b.received_total) / count(*), 2) AS avg_bill_value,
|
||||
round(sum(b.received_total) / NULLIF(sum(b.guest_count), 0), 2) AS avg_guest_value,
|
||||
round(sum(b.discount_total) / NULLIF(sum(b.consumption), 0) * 100, 2) AS discount_rate_pct,
|
||||
round(sum(b.theoretical_profit) / NULLIF(sum(b.received_total), 0) * 100, 2) AS theoretical_margin_pct,
|
||||
round(count(*) FILTER (WHERE b.member_id IS NOT NULL)::numeric / count(*) * 100, 2) AS member_bill_share_pct
|
||||
FROM analytics.bill_fact b
|
||||
WHERE b.closed_at >= analytics.fn_month_start_ts(p_month)
|
||||
AND b.closed_at < analytics.fn_next_month_start_ts(p_month)
|
||||
GROUP BY b.store_code, b.store_name
|
||||
),
|
||||
anomaly AS (
|
||||
SELECT
|
||||
a.store_code,
|
||||
round(count(*)::numeric / NULLIF(bc.bill_count, 0) * 100, 2) AS anomaly_rate_pct
|
||||
FROM analytics.v_anomaly_bills a
|
||||
JOIN (SELECT store_code, count(*) AS bill_count FROM analytics.bill_fact
|
||||
WHERE closed_at >= analytics.fn_month_start_ts(p_month)
|
||||
AND closed_at < analytics.fn_next_month_start_ts(p_month)
|
||||
GROUP BY store_code) bc ON a.store_code = bc.store_code
|
||||
WHERE a.closed_at >= analytics.fn_month_start_ts(p_month)
|
||||
AND a.closed_at < analytics.fn_next_month_start_ts(p_month)
|
||||
GROUP BY a.store_code, bc.bill_count
|
||||
),
|
||||
combined AS (
|
||||
SELECT
|
||||
b.*,
|
||||
COALESCE(an.anomaly_rate_pct, 0) AS anomaly_rate_pct,
|
||||
CASE
|
||||
WHEN b.received IS NULL OR b.received = 0 THEN '绿色'
|
||||
WHEN b.theoretical_margin_pct < 68 OR b.discount_rate_pct > 25 OR COALESCE(an.anomaly_rate_pct, 0) > 3 THEN '红色'
|
||||
WHEN b.theoretical_margin_pct >= 70 AND b.discount_rate_pct <= 22 AND COALESCE(an.anomaly_rate_pct, 0) <= 1.5 THEN '绿色'
|
||||
ELSE '黄色'
|
||||
END AS risk_level,
|
||||
CASE
|
||||
WHEN b.theoretical_margin_pct < 68 AND b.discount_rate_pct > 25 AND COALESCE(an.anomaly_rate_pct, 0) > 3 THEN '毛利率低;优惠率高;异常率高'
|
||||
WHEN b.theoretical_margin_pct < 68 AND b.discount_rate_pct > 25 THEN '毛利率低;优惠率高'
|
||||
WHEN b.theoretical_margin_pct < 68 AND COALESCE(an.anomaly_rate_pct, 0) > 3 THEN '毛利率低;异常率高'
|
||||
WHEN b.discount_rate_pct > 25 AND COALESCE(an.anomaly_rate_pct, 0) > 3 THEN '优惠率高;异常率高'
|
||||
WHEN b.theoretical_margin_pct < 68 THEN '毛利率低'
|
||||
WHEN b.discount_rate_pct > 25 THEN '优惠率高'
|
||||
WHEN COALESCE(an.anomaly_rate_pct, 0) > 3 THEN '异常率高'
|
||||
ELSE ''
|
||||
END AS primary_issue
|
||||
FROM base b
|
||||
LEFT JOIN anomaly an ON b.store_code = an.store_code
|
||||
)
|
||||
SELECT
|
||||
store_code, store_name, bill_count, active_days, received,
|
||||
avg_daily_received, avg_bill_value, avg_guest_value,
|
||||
discount_rate_pct, theoretical_margin_pct, member_bill_share_pct,
|
||||
anomaly_rate_pct, risk_level, primary_issue
|
||||
FROM combined
|
||||
$$ LANGUAGE SQL STABLE;
|
||||
Reference in New Issue
Block a user