77 lines
2.8 KiB
Python
77 lines
2.8 KiB
Python
"""快速诊断 SPI 溢出 - 直接查 dwd_settlement_head"""
|
|
import os, math
|
|
from pathlib import Path
|
|
from dotenv import load_dotenv
|
|
import psycopg2
|
|
|
|
load_dotenv(Path(__file__).resolve().parents[2] / ".env")
|
|
dsn = os.environ["PG_DSN"]
|
|
conn = psycopg2.connect(dsn, connect_timeout=10)
|
|
cur = conn.cursor()
|
|
sid = 2790685415443269
|
|
|
|
# 1. 查消费极值
|
|
cur.execute("""
|
|
SELECT MAX(pay_amount), MIN(pay_amount), COUNT(*)
|
|
FROM dwd.dwd_settlement_head
|
|
WHERE site_id = %s AND settle_type IN (1,3)
|
|
AND pay_time >= NOW() - INTERVAL '90 days'
|
|
""", (sid,))
|
|
r = cur.fetchone()
|
|
print(f"settle_head 90d: max={r[0]}, min={r[1]}, count={r[2]}")
|
|
|
|
# 2. 模拟最大 score
|
|
max_pay = float(r[0] or 0)
|
|
level = (0.30 * math.log1p(max_pay/500) + 0.30 * math.log1p(max_pay/1500)
|
|
+ 0.20 * math.log1p(max_pay/200) + 0.20 * math.log1p(0/1000))
|
|
speed_abs = math.log1p(max_pay / (1 * 100))
|
|
speed = 0.40 * speed_abs
|
|
raw = 0.60 * level + 0.30 * speed
|
|
print(f"Simulated max: level={level:.4f}, speed_abs={speed_abs:.4f}, speed={speed:.4f}, raw={raw:.4f}")
|
|
|
|
# 3. 查 SPIMemberFeatures 的 dataclass 定义中 daily_spend_ewma_90 的范围
|
|
# 先看 member 级聚合后的极值
|
|
cur.execute("""
|
|
WITH cs AS (
|
|
SELECT COALESCE(NULLIF(s.member_id, 0), 0) AS mid,
|
|
SUM(COALESCE(s.pay_amount, 0)) AS spend_90,
|
|
SUM(CASE WHEN pay_time >= NOW() - INTERVAL '30 days' THEN COALESCE(pay_amount,0) ELSE 0 END) AS spend_30,
|
|
COUNT(*) AS orders_90
|
|
FROM dwd.dwd_settlement_head s
|
|
WHERE s.site_id = %s AND s.settle_type IN (1,3)
|
|
AND s.pay_time >= NOW() - INTERVAL '90 days'
|
|
GROUP BY mid
|
|
)
|
|
SELECT mid, spend_30, spend_90, orders_90,
|
|
spend_90 / GREATEST(orders_90, 1) AS avg_ticket
|
|
FROM cs ORDER BY spend_90 DESC LIMIT 5
|
|
""", (sid,))
|
|
print("\nTop 5 spenders:")
|
|
for r in cur.fetchall():
|
|
mid, s30, s90, o90, tk = r
|
|
s30f, s90f, tkf = float(s30), float(s90), float(tk)
|
|
lv = (0.30*math.log1p(s30f/500) + 0.30*math.log1p(s90f/1500)
|
|
+ 0.20*math.log1p(tkf/200) + 0.20*0)
|
|
sp = 0.40*math.log1p(s30f/(1*100))
|
|
rw = 0.60*lv + 0.30*sp
|
|
print(f" mid={mid}, s30={s30}, s90={s90}, o90={o90}, tk={tk:.2f}, level={lv:.4f}, speed={sp:.4f}, raw={rw:.4f}")
|
|
|
|
# 4. 检查 site_id 本身是否超出 integer 范围
|
|
print(f"\nsite_id={sid}, int32 max={2**31-1}, int64 max={2**63-1}")
|
|
print(f"site_id > int32? {sid > 2**31-1}")
|
|
print(f"site_id fits int64? {sid < 2**63-1}")
|
|
|
|
# 5. 检查 dws_member_spending_power_index 的 site_id 列类型
|
|
cur.execute("""
|
|
SELECT column_name, data_type, numeric_precision
|
|
FROM information_schema.columns
|
|
WHERE table_schema='dws' AND table_name='dws_member_spending_power_index'
|
|
AND column_name IN ('site_id', 'member_id')
|
|
""")
|
|
print(f"\nKey column types:")
|
|
for r in cur.fetchall():
|
|
print(f" {r[0]}: {r[1]} (precision={r[2]})")
|
|
|
|
conn.close()
|
|
print("\n完成")
|