在同一个SELECT sql查询中从SUM()计算百分比 [英] Compute percents from SUM() in the same SELECT sql query
问题描述
在表 my_obj
中有两个整数字段:
(value_a integer,value_b integer);
我尝试计算 value_a = value_b
,我想用百分比表示这个比率。
这是我试过的代码:
select sum(o.value_a = o.value_b then 1 else 0 end)as nb_ok,
sum(case when o.value_a!= o.value_b then 1 else 0 end)as nb_not_ok,
compute_percent(nb_ok,nb_not_ok)
from my_obj as o
group by o.property_name;
compute_percent
是一个stored_procedure, code>(a * 100)/(a + b)
但是PostgreSQL抱怨列 nb_ok
不存在。
如何正确地执行?
我使用PostgreSQL 9.1与Ubuntu 12.04。
这个问题比它看起来多。
简单版本
这是很多更快更简单:
SELECT property_name
,(count(value_a = value_b或NULL)* 100)/ count(*)AS pct
FROM my_obj
GROUP BY 1;
结果:
code> property_name | pct
-------------- + ----
prop_1 | 17
prop_2 | 43
如何?
-
你根本不需要一个函数。
-
而不是计算
value_b
(您不需要开始) ,请使用count(*)
作为总计。 -
这假设您没有
NULL
值。也就是说两个列都定义NOT NULL
。您的问题中缺少信息。
如果没有,您的原始查询为可能不会执行您认为的。如果任何值为NULL,则您的版本不会对该行计数。你甚至可以用这种方式引发一个除零异常。
此版本也使用NULL。count(*)
产生所有行的计数,而不管值。
<工程:
TRUE OR NULL = TRUE
FALSE或NULL = NULL
count()
忽略NULL值。 Voilá。
运算符优先支配 =
在或
之前绑定。您可以添加括号以使其更清楚:
count((value_a = value_b)OR FALSE)
您也可以使用
count NULLIF(< expression>,FALSE)
结果类型默认情况下 count()
的默认值为 bigint
。
分区 bigint / bigint
,截断小数位数。
小数位
使用 100.0
(带小数数字)强制计算 numeric
,从而保留小数位数。
您可以使用 round()
:
SELECT property_name
,round((count(value_a = value_b OR NULL)* 100.0)/ count(*),2)AS pct
FROM my_obj
GROUP BY 1;
结果:
code> property_name | pct
-------------- + -------
prop_1 | 17.23
prop_2 | 43.09
另外:
我使用 value_a
而不是 valueA
。不要在PostgreSQL中使用不带引号的混合大小写标识符。我看到太多的绝望的问题来自这个蠢事。如果您不知道我在说什么,请参阅标识符和关键字。
In the table my_obj
there are two integer fields:
(value_a integer, value_b integer);
I try to compute how many time value_a = value_b
, and I want to express this ratio in percents.
This is the code I have tried:
select sum(case when o.value_a = o.value_b then 1 else 0 end) as nb_ok,
sum(case when o.value_a != o.value_b then 1 else 0 end) as nb_not_ok,
compute_percent(nb_ok,nb_not_ok)
from my_obj as o
group by o.property_name;
compute_percent
is a stored_procedure that simply does (a * 100) / (a + b)
But PostgreSQL complains that the column nb_ok
doesn't exist.
How would you do that properly ?
I use PostgreSQL 9.1 with Ubuntu 12.04.
There is more to this question than it may seem.
Simple version
This is much faster and simpler:
SELECT property_name
,(count(value_a = value_b OR NULL) * 100) / count(*) AS pct
FROM my_obj
GROUP BY 1;
Result:
property_name | pct
--------------+----
prop_1 | 17
prop_2 | 43
How?
You don't need a function for this at all.
Instead of counting
value_b
(which you don't need to begin with) and calculating the total, usecount(*)
for the total. Faster, simpler.This assumes you don't have
NULL
values. I.e. both columns are definedNOT NULL
. The information is missing in your question.
If not, your original query is probably not doing what you think it does. If any of the values is NULL, your version does not count that row at all. You could even provoke a division-by-zero exception this way.
This version works with NULL, too.count(*)
produces the count of all rows, regardless of values.Here's how the count works:
TRUE OR NULL = TRUE FALSE OR NULL = NULL
count()
ignores NULL values. Voilá.Operator precedence governs that
=
binds beforeOR
. You could add parentheses to make it clearer:count ((value_a = value_b) OR FALSE)
You can do the same with
count NULLIF(<expression>, FALSE)
The result type of
count()
isbigint
by default.
A divisionbigint / bigint
, truncates fractional digits.
Include fractional digits
Use 100.0
(with fractional digit) to force the calculation to be numeric
and thereby preserve fractional digits.
You may want to use round()
with this:
SELECT property_name
,round((count(value_a = value_b OR NULL) * 100.0) / count(*), 2) AS pct
FROM my_obj
GROUP BY 1;
Result:
property_name | pct
--------------+-------
prop_1 | 17.23
prop_2 | 43.09
As an aside:
I use value_a
instead of valueA
. Don't use unquoted mixed-case identifiers in PostgreSQL. I have seen too many desperate question coming from this folly. If you wonder what I am talking about, read the chapter Identifiers and Key Words in the manual.
这篇关于在同一个SELECT sql查询中从SUM()计算百分比的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!