PostgreSQL使用count()确定百分比(广播问题)


19

我正在尝试运行以下查询,以提供patients表中具有该refinst列值的行的百分比。我一直得到0的结果。

select (count (refinst) / (select count(*) from patients) * 100) as "Formula" 
from patients;

该表有15556行,并select count(refinst) from patients告诉我其中的1446 行在该refinst列中有一个值。我想从查询中获得的响应为30.62(1446/15556*100=30.62XXXXX,四舍五入为两位小数)。

我很确定它与计数结果的数据类型有关(我假设的是整数)。如果我将整数除以整数并且结果小于0,则将其截断为0正确吗?如果是这样,有人可以告诉我如何将计数结果转换为2位小数的数字,以便结果也将四舍五入到2位小数吗?

我敢肯定,与多个count语句相比,有一种更好的方法来编写此代码。我正在寻找一种更处理器有效的方法来特别编写此查询。


也许这个答案可以帮助您。
Jhon Anderson Cardenas Diaz

Answers:


26
SELECT (count(refinst) * 100)::numeric / count(*) AS refinst_percentage
FROM   patients;
  • 千万不能使用子查询。两种聚合都可以从同一查询中派生。便宜点

  • 同样,对于窗口函数也不是这种情况,因为您只想计算一个结果,而不是每行一个结果。

  • 强制转换为支持小数位的任何数字类型,例如@a_horse已解释
    由于您想输入round()两位小数,因此建议使用numeric(与decimalPostgres中的相同)。
    但这足以转换一个涉及计算的值,最好是第一个。Postgres自动适应不会丢失信息的类型。

  • 通常,除法之前先进行乘法是一个好主意。通常,这可最大程度地减少舍入误差,并且更便宜。
    在这种情况下,count(refinst) * 100可以用便宜而精确的integer算术来计算第一个乘法()。只有这样,我们才能投射到numeric下一个并除以下一个integer(我们不会额外投射)。

四舍五入为两个小数位:

SELECT round((count(refinst) * 100)::numeric / count(*), 2) AS refinst_percentage
FROM   patients;

当然您是对的,不需要窗口功能。但这并没有真正的改变(除了可读性之外)。
a_horse_with_no_name 2014年

3

您需要将除法中涉及的每个数字转换为支持小数的类型:

select (count(refinst)::decimal / (select count(*) from patients)::decimal) * 100  as "Formula" 
from patients;

您可能还想尝试使用窗口函数而不是标量子查询。可能会更快:

select (count(refinst)::decimal / (count(*) over ())::decimal) * 100 as "Formula" 
from patients;

0

我知道这个线程已经使用了两年了,但是:尝试乘以100.0而不是100。那应该自动将结果强制转换为浮点数而不是整数。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.