除以零异常问题

Division by zero exception issue

提问人:Steven 提问时间:7/25/2023 更新时间:7/25/2023 访问量:32

问:

我正在运行这个查询,我计算:

  • 上一期间的活跃用户数
  • 回访用户数(上期和本期活跃用户数)
  • 留存率 ( returning_users/previous_period_active_user)

问题是“previous_period_active_user”和“returning_user”返回正确的结果,但“retention_rate”总是返回零。 我不明白我做错了什么。我知道PostgreSQL中的除以零错误,这就是我使用COALESCE和NULIF函数的原因。

查询:

SELECT
    au.time_gran,
    au.time,
    au.country,
    count(DISTINCT au.user_id) FILTER (WHERE au.active_1_period_before) AS previous_period_active_user,
    count(DISTINCT au.user_id) FILTER (WHERE au.active AND au.active_1_period_before) AS returning_users,
    COALESCE(
        count(DISTINCT CASE WHEN au.active AND au.active_1_period_before THEN au.user_id END) /
        NULLIF(count(DISTINCT au.user_id) FILTER (WHERE au.active_1_period_before), 0),
        0
    ) AS retention_rate
FROM active_users au
PostgreSQL 合并 nullif

评论


答:

1赞 SelVazi 7/25/2023 #1

当您在除法中仅使用整数时,您将获得整数除法。

count()返回整数,因此您需要将它们转换为浮点数作为计算的一部分(乘以):1.0

SELECT
    au.time_gran,
    au.time,
    au.country,
    count(DISTINCT au.user_id) FILTER (WHERE au.active_1_period_before) AS previous_period_active_user,
    count(DISTINCT au.user_id) FILTER (WHERE au.active AND au.active_1_period_before) AS returning_users,
    COALESCE(
        count(DISTINCT CASE WHEN au.active AND au.active_1_period_before THEN au.user_id END) * 1.0 /
        NULLIF(count(DISTINCT au.user_id) FILTER (WHERE au.active_1_period_before) * 1.0, 0),
        0
    ) AS retention_rate
FROM active_users au
group by au.time_gran, au.time, au.country

评论

1赞 Jonathan Willcock 7/25/2023
postgresql 中的次要点返回 。countbigint
0赞 SelVazi 7/25/2023
好点@JonathanWillcock
0赞 Jonathan Willcock 7/25/2023
乘以 1.0 的另一个有趣的技巧 - 我在您发布之前写的答案使用了 cast。乘以 1.0 更快/更有效吗?
1赞 SelVazi 7/25/2023
只是打:)更快.不确定哪个更快* 1.0