You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL按用户分组计算投注正确率比率问题求助

解决按年度用户统计投注正确率时比率一致的问题

我猜你大概率是踩了SQL分组统计里的几个常见坑之一,咱们一步步拆解问题根源,再给你靠谱的解决方案:

最可能的几个问题点

1. 分组字段不完整,把多个用户合并成了同一组

如果你的GROUP BY子句只写了年度(比如su.year),没把用户的唯一标识(比如user_id或者username)加进去,那SQL会把同一年度的所有用户数据合并计算,得到的自然是整个年度的全局正确率,而不是单个用户的年度正确率。

举个反例,错误写法:

SELECT u.username, su.year, 
       COUNT(CASE WHEN b.Status='Correct' THEN 1 END)/COUNT(b.id) AS accuracy
FROM SeasonalUser su
JOIN "User" u ON su.user_id = u.id
JOIN bets_bet b ON su.user_id = b.user_id
GROUP BY su.year; -- 这里只按年度分组,大错特错!

2. 多表关联时没绑定年度,导致统计了用户所有年份的投注

如果你的bets_bet表有投注时间字段(比如bet_date),但关联SeasonalUser时没加上年度匹配的条件,那会把该用户所有年份的投注都关联到每一条年度记录上,这样每个年度统计的其实是用户所有投注的总比率,自然所有年度的比率都一样。

3. 用了全局聚合的子查询,而非分组内的聚合

要是你用了不带关联条件的子查询来计算正确数和总数(比如(SELECT COUNT(*) FROM bets_bet WHERE Status='Correct')),那这个子查询返回的是全表的全局统计值,每个用户的分组都会复用这个值,结果当然全相同。

正确的SQL写法示例

假设bets_bet有bet_date字段用来确定投注所属年度,咱们写一个标准的统计语句:

SELECT
    u.username,
    su.year,
    -- 处理除以0的情况,避免报错;转成浮点确保得到小数比率
    COALESCE(
        COUNT(CASE WHEN b.Status = 'Correct' THEN 1 END) * 1.0 / NULLIF(COUNT(b.id), 0),
        0.0
    ) AS accuracy_rate
FROM
    SeasonalUser su
JOIN
    "User" u ON su.user_id = u.id
-- 用LEFT JOIN避免过滤掉无投注的年度用户记录
LEFT JOIN
    bets_bet b 
    ON su.user_id = b.user_id 
    AND EXTRACT(YEAR FROM b.bet_date) = su.year -- 关键:绑定年度关联
GROUP BY
    u.id, u.username, su.year -- 用user_id分组更可靠,避免用户名重复
ORDER BY
    su.year, accuracy_rate DESC;

快速排查步骤

  1. 先去掉GROUP BY,看JOIN后的原始数据是否正确:每个用户的年度记录只对应该年度的投注,没有跨年度的冗余数据。
  2. 检查GROUP BY子句:必须包含用户唯一标识(user_id)和年度(su.year),确保每个分组是「单个用户+单个年度」的组合。
  3. 验证聚合逻辑:确保COUNT、SUM这类函数是针对当前分组计算的,不要用全局子查询。

内容的提问来源于stack exchange,提问作者Pablo Ruiz Ruiz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:47:59