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

PostgreSQL多CTE运算结果异常:整数除法致结果为0

问题根源:整数除法的取整特性

PostgreSQL中,两个整数做除法时会自动舍弃小数部分取整。你的主队获胜数、客队获胜数和总比赛数都是整数类型,当获胜数小于总比赛数时,整数/整数的结果就会被截断为0,这就是你得到异常结果的原因。

修复现有代码的方法

只需要把除法运算中的任意一个数值转换为浮点类型,强制PostgreSQL执行浮点除法即可。修改后的代码如下:

WITH home_team_wins (match) AS (
        SELECT match
        FROM penalties
        WHERE neutral_stadium = 0
            AND attacker_home = 1
            AND match_winner = 1
        GROUP BY match
    ),
    away_team_wins (match) AS (
        SELECT match
        FROM penalties
        WHERE neutral_stadium = 0
            AND attacker_home = 0
            AND match_winner = 1
    ),
    num_home_wins (match) AS (
        SELECT COUNT(DISTINCT match)
        FROM home_team_wins
    ),
    num_away_wins (match) AS (
        SELECT COUNT(DISTINCT match)
        FROM away_team_wins
    ),
    total_matches (match_count) AS (
        SELECT COUNT(DISTINCT match)
        FROM penalties
        WHERE neutral_stadium = 0
    )
SELECT 
    num_home_wins.match::FLOAT / total_matches.match_count AS home_win_percentage,
    num_away_wins.match::FLOAT / total_matches.match_count AS away_win_percentage
FROM num_home_wins, num_away_wins, total_matches;

你也可以用CAST(num_home_wins.match AS FLOAT)或者num_home_wins.match * 1.0来实现同样的类型转换效果。

更高效的实现方式

你当前的多CTE写法会多次扫描表,效率偏低。可以通过一次聚合查询完成所有统计,逻辑更简洁且性能更好:

SELECT
    COUNT(DISTINCT CASE WHEN attacker_home = 1 AND match_winner = 1 THEN match END)::FLOAT / COUNT(DISTINCT match) AS home_win_percentage,
    COUNT(DISTINCT CASE WHEN attacker_home = 0 AND match_winner = 1 THEN match END)::FLOAT / COUNT(DISTINCT match) AS away_win_percentage
FROM penalties
WHERE neutral_stadium = 0;

或者用分组统计的方式,可读性更强:

WITH match_results AS (
    SELECT 
        DISTINCT match,
        CASE 
            WHEN attacker_home = 1 AND match_winner = 1 THEN 'home_win'
            WHEN attacker_home = 0 AND match_winner = 1 THEN 'away_win'
        END AS result
    FROM penalties
    WHERE neutral_stadium = 0
)
SELECT
    SUM(CASE WHEN result = 'home_win' THEN 1 ELSE 0 END)::FLOAT / COUNT(*) AS home_win_percentage,
    SUM(CASE WHEN result = 'away_win' THEN 1 ELSE 0 END)::FLOAT / COUNT(*) AS away_win_percentage
FROM match_results;

内容的提问来源于stack exchange,提问作者23manders

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 10:45:19