计算PostgreSQL中的计数比率

toiithl6  于 2022-11-23  发布在  PostgreSQL
关注(0)|答案(1)|浏览(238)

我在Postgres 14数据库中有一个表mydata,它包含以下相关列:

  • ftype:具有foobarbazenum
  • status:具有pendingfailedsuccess的另一个enum

我想要不同类型的成功率。成功率基本上是:status等于success的行数除以该ftype的总行数。
目前,我正在执行以下操作:

SELECT
    COALESCE(
        COUNT(CASE WHEN ftype = 'foo' AND status = 'success' THEN 1 END) / 
        NULLIF(COUNT(CASE WHEN ftype = 'foo' THEN 1 END)::real, 0)
    ,0)::real AS foo_rate,

    COALESCE(
        COUNT(CASE WHEN ftype = 'bar' AND status = 'success' THEN 1 END) / 
        NULLIF(COUNT(CASE WHEN ftype = 'bar' THEN 1 END)::real, 0)
    ,0)::real AS bar_rate,

    COALESCE(
        COUNT(CASE WHEN ftype = 'baz' AND status = 'success' THEN 1 END) / 
        NULLIF(COUNT(CASE WHEN ftype = 'baz' THEN 1 END)::real, 0)
    ,0)::real AS baz_rate,
FROM mydata;

是否有更好/更高性能的方法?如何优化它?
在查询中使用PARTITION是否有帮助?

yjghlzjz

yjghlzjz1#

由于您要计算所有类型的比率,因此枢纽分析的结果会比较简单:

SELECT ftype, CASE WHEN ct_success = 0 THEN 0 ELSE ct_success/ct_total END AS rate
FROM  (
   SELECT ftype
        , count(*) AS ct_total
        , count(*) FILTER (WHERE status = 'success')::real AS ct_success
   FROM   mydata
   GROUP  BY 1
   ) sub;

也适用于多种类型。(不过好处较小。)尽早过滤:

SELECT ftype, CASE WHEN ct_success = 0 THEN 0 ELSE ct_success/ct_total END AS rate
FROM  (
   SELECT ftype
        , count(*) AS ct_total
        , count(*) FILTER (WHERE status = 'success')::real AS ct_success
   FROM   mydata
   WHERE  ftype = ANY ('{foo,bar,baz}'::my_enum_type[])  -- here!
   GROUP  BY 1
   ) sub;

关于WHERE子句:

  • PostgreSQL中的IN与ANY运算符

您可能需要使用round()和/或numeric作为开始。请参阅:

  • 如何将真实的类型舍入为NUMERIC?
  • 数值修约

关于聚合FILTER子句:

  • 使用其他(非重复)筛选器聚合列

table partitioning是否有帮助很难从我们所拥有的最少信息中判断出来。手册中的“概述”一章中有关于“表分区”的有用指导。我有根据的猜测是它不会对您有好处。

相关问题