如何在 Postgres 中构建一个函数来计算两个 "select count(*)" 查询的百分比?
how to build a function in Postgres that calculats Percentage from two "select count(*)" queries?
我正在尝试构建一个函数来返回具有特定条件的行的百分比。
这是我的尝试:
CREATE OR REPLACE FUNCTION osm_prozent ()
RETURNS integer AS $$
DECLARE
a integer;
b integer;
ergebnis integer;
BEGIN
a = select into a count(*)
from osm_street;
b = select into b count(*)
from osm_street
where hausnummer like '%-%'
or hausnummer like '% %'
or hausnummer like '%/%'
or hausnummer like '%;%'
or hausnummer like '%,%'
or hausnummer ~ '([a-z,A-Z])';
ergebnis = (b/a)*100;
return ergebnis;
END;
$$ LANGUAGE plpgsql;
变量 a
是 207000
变量 b
是 11000.
最后我应该有类似 5.31%
.
的东西
谁能帮忙正确写出这个函数?
您的正则表达式过滤器加上几个赞可以简化为单个正则表达式(另请注意,您的正则表达式通过添加括号增加了不必要的负载,a-z 和 A-Z 之间的逗号不是分隔符,而是匹配还有逗号,您还在类似比较列表中包含了 TWICE!)。一个更简单的函数代码是:
CREATE OR REPLACE FUNCTION osm_prozent () RETURNS double precision AS $$
SELECT 100. * (SELECT COUNT(*) FROM osm_street WHERE hausnummer ~* '[a-z /;,-]') / (SELECT COUNT(*) FROM osm_street);
$$ LANGUAGE sql;
您可以进行两项明显的改进,按重要性排序:
- 让 table 传球 1 次,而不是传球 2 次
- 简化第二个查询的 where 条件
先处理第二项:
可以使用一个正则表达式测试将where条件更改为只有一个比较。这个表达式:
where hausnummer like '%-%'
or hausnummer like '% %'
or hausnummer like '%/%'
or hausnummer like '%;%'
or hausnummer like '%,%'
or hausnummer ~ '([a-z,A-Z])'
可以简单地表示为:
where hausnummer ~ '[a-z,A-Z /;-]'
接下来,为了仅通过 table,在条件上使用 sum()
以在捕获 count(*)
的同时捕获命中数。使用上面的改进作为条件,你的查询可以变成:
select 100.0 * sum(case when hausnummer ~ '[a-z,A-Z /;-]' then 1 end) / count(*)
from osm_street
除非您需要一个存储过程,否则您现在可以完全放弃它,因为您只需一个简单的查询即可获得结果。
如果您迫切需要一个存储过程(不推荐),它只是上述查询的一个薄包装(不增加任何价值):
CREATE OR REPLACE FUNCTION osm_prozent () RETURNS double precision AS $$
BEGIN
RETURN select 100.0 * sum(case when hausnummer ~ '[a-z,A-Z /;-]' then 1 end) / count(*) from osm_street;
END;
$$ LANGUAGE plpgsql;
请注意,我怀疑你最后的条件 hausnummer ~ '([a-z,A-Z])'
不是你想要的。首先,括号是多余的,可以在不改变含义的情况下将其删除,即它与 hausnummer ~ '[a-z,A-Z]'
相同,并且如果 hausnummber
包含字母或逗号则为真。
如果这不是您想要的,请对此答案发表评论,解释您真正想要的。
我正在尝试构建一个函数来返回具有特定条件的行的百分比。
这是我的尝试:
CREATE OR REPLACE FUNCTION osm_prozent ()
RETURNS integer AS $$
DECLARE
a integer;
b integer;
ergebnis integer;
BEGIN
a = select into a count(*)
from osm_street;
b = select into b count(*)
from osm_street
where hausnummer like '%-%'
or hausnummer like '% %'
or hausnummer like '%/%'
or hausnummer like '%;%'
or hausnummer like '%,%'
or hausnummer ~ '([a-z,A-Z])';
ergebnis = (b/a)*100;
return ergebnis;
END;
$$ LANGUAGE plpgsql;
变量 a
是 207000
变量 b
是 11000.
最后我应该有类似 5.31%
.
谁能帮忙正确写出这个函数?
您的正则表达式过滤器加上几个赞可以简化为单个正则表达式(另请注意,您的正则表达式通过添加括号增加了不必要的负载,a-z 和 A-Z 之间的逗号不是分隔符,而是匹配还有逗号,您还在类似比较列表中包含了 TWICE!)。一个更简单的函数代码是:
CREATE OR REPLACE FUNCTION osm_prozent () RETURNS double precision AS $$
SELECT 100. * (SELECT COUNT(*) FROM osm_street WHERE hausnummer ~* '[a-z /;,-]') / (SELECT COUNT(*) FROM osm_street);
$$ LANGUAGE sql;
您可以进行两项明显的改进,按重要性排序:
- 让 table 传球 1 次,而不是传球 2 次
- 简化第二个查询的 where 条件
先处理第二项:
可以使用一个正则表达式测试将where条件更改为只有一个比较。这个表达式:
where hausnummer like '%-%'
or hausnummer like '% %'
or hausnummer like '%/%'
or hausnummer like '%;%'
or hausnummer like '%,%'
or hausnummer ~ '([a-z,A-Z])'
可以简单地表示为:
where hausnummer ~ '[a-z,A-Z /;-]'
接下来,为了仅通过 table,在条件上使用 sum()
以在捕获 count(*)
的同时捕获命中数。使用上面的改进作为条件,你的查询可以变成:
select 100.0 * sum(case when hausnummer ~ '[a-z,A-Z /;-]' then 1 end) / count(*)
from osm_street
除非您需要一个存储过程,否则您现在可以完全放弃它,因为您只需一个简单的查询即可获得结果。
如果您迫切需要一个存储过程(不推荐),它只是上述查询的一个薄包装(不增加任何价值):
CREATE OR REPLACE FUNCTION osm_prozent () RETURNS double precision AS $$
BEGIN
RETURN select 100.0 * sum(case when hausnummer ~ '[a-z,A-Z /;-]' then 1 end) / count(*) from osm_street;
END;
$$ LANGUAGE plpgsql;
请注意,我怀疑你最后的条件 hausnummer ~ '([a-z,A-Z])'
不是你想要的。首先,括号是多余的,可以在不改变含义的情况下将其删除,即它与 hausnummer ~ '[a-z,A-Z]'
相同,并且如果 hausnummber
包含字母或逗号则为真。
如果这不是您想要的,请对此答案发表评论,解释您真正想要的。