2016-03-31 2 views
2

特定の条件を持つ行の割合を返す関数を作成しようとしています。ここで2つの "select count(*)"クエリからPercentageを計算するPostgresで関数を作成する方法は?

は私の試みです:

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; 

変数a207000、変数bで終わりに私は5.31%のようなものを持っている必要があり11000.されます。

誰かがこの機能を正しく書き込めますか?

+0

(b/a)* 100を使用すると、5.31が得られます。あなたの計算では、bはあなたが6%を得る方法よりも高いです – Sathish

答えて

3

あなたは重要度の順に、2点の明確な改善を行うことができます。

  1. テーブルの上に1つのパスの代わりに、2回のパス
  2. 簡素化状態のを確認しますあなたの2番目のクエリ最初の2番目の項目に対処

where条件は、ちょうど正規表現テストを使ってただ1つの比較を持つように変更することができます。この式:

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(*)をキャプチャします。条件として上記の改善を使用して、クエリになることができます:あなたは1つの単純なクエリで結果を持っているよう

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に文字またはカンマが含まれている場合はtrueです。

でない場合は、あなたが実際に望むものを説明するこの回答にコメントを残してください。

+0

実際にOPとは何ですか?欲しいだけでは決してコメントに入るべきではありません。それは疑問に残るはずです。そして、私はあなたがストアドプロシージャを意味する "ストアプロシージャ"と仮定しますか? Postgresにはストアドプロシージャはありませんが、ほとんど同じではありませんが、まったく同じではありません。 –

+0

@erwin私はデータベースの知識を大いに尊重していますが、私はあなたにPGを「ぶち壊した手順がない」という髪を分けていると思います。 [doc](http://www.postgresql.org/docs/9.0/static/plpgsql-overview.html)には、* PL/pgSQL ...を使って関数やトリガプロシージャ*を作成し、それらを格納することができますので、ストアドプロシージャです。また、「ストアドプロシージャ」は、業界の一般的な用語です。さらに、Postgresの文脈でこれらのものをストアドプロシージャと呼ぶことは、誤解を招く、または混乱を招く可能性があるIMHOはありません。 – Bohemian

+0

重要な違いは、Postgresの関数(実際のストアドプロシージャではなく)は常に1つのトランザクション内で実行されるため、トランザクションを開始またはコミットできず、トランザクション内では実行できない 'VACUUM'や' CREATE INDEX CONCURRENTLY'ブロック)。その他:http://stackoverflow.com/a/28251922/939860 –

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; 
+0

こんにちは、私はこのエラーが発生しています:ERROR:演算子が存在しません:テキスト*〜不明 行2:...(SELECT COUNT(*)FROM osm_street WHERE hausnummer *〜 '[az/... ^ ヒント:与えられた名前と引数の型が一致する演算子がありません。明示的な型キャストを追加する必要があるかもしれません。 –

+0

申し訳ありませんが、 '〜'は大文字と小文字を区別しない正規表現のマッチを使いますが、 '〜*'は大文字と小文字を区別しない正規表現のマッチを使用します:) –

関連する問題