我正在尝试构建一个函数,该函数返回具有特定条件的行的百分比。
这是我的尝试:
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%
的内容。
有人可以帮助正确编写此功能吗?
答案 0 :(得分:3)
您可以按重要性顺序做出两项明确的改进:
首先处理第二项:
可以使用一个正则表达式测试将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 /;-]'
接下来,要仅对表格进行一次传递,请在条件上使用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
包含字母或逗号,则为真。
如果那是不您的意图,请在此答案中留言,说明您的实际需求。
答案 1 :(得分:0)
通过正则表达式与多个喜欢混合使用的过滤器可以简化为单个正则表达式(另请注意,正则表达式通过添加括号添加不必要的负载,并且az和AZ之间的逗号不是分隔符,但匹配逗号为好吧,你还在你的比较列表中包含了 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;