一つの方法:
SELECT c, count(*) AS ct, (count(*) * 100)/length($1) AS pct
FROM unnest(string_to_array($1, NULL)) c
WHERE length($1) > 7 -- maybe a length condition of 8 or more
GROUP BY 1
HAVING count(*) > (length($1) * 80)/100 -- 80 is your % threshold
ORDER BY 2 DESC;
$1
が分析される文字列であること。
与えられたテキストの80%以上を占める文字を返します。明らかにパーセンテージが50以上の場合は1行にすることはできません。文字が十分に頻繁に使用されていない場合は何もしません。
(count(*) * 100)/length($1)
は、整数除算で丸めて計算する最も簡単な方法です。正確な結果が必要な場合は、代わりにcount(*) >= (length($1) * 80)/100.0
を使用してください(ここでも>=
を書き留めてください)。 (100.0
は計算結果をnumeric
と厳密に一致させる)
これを関数または準備文に簡単にラップし、文字列とパーセントをパラメータとして渡すことができます。
CREATE OR REPLACE FUNCTION f_char_pct(_word text, _pct int)
RETURNS boolean AS
$func$
SELECT EXISTS (
SELECT 1
FROM unnest(string_to_array(_word, NULL)) c
GROUP BY c
HAVING count(*) > (length(_word) * _pct)/100
)
$func$ LANGUAGE sql IMMUTABLE;
コール:
「与えられた文書内の単一の単語が7つの以上の文字と所定のしきい値以下の文字の割合で存在する場合、false
を返すエルスtrue
」
ので、同様
SELECT NOT EXISTS (
SELECT 1
FROM unnest(string_to_array('1000000000000z abc 1234567890', ' ')) word
WHERE length(word) > 7
AND NOT f_char_pct(word, 80)
);
返信false
です。
'abc'は無視され、他の2つの単語は同じ文字の> 80%を持つため、true
'1000000000000z abc 2222222'が返されます。
NULL入力btwの場合はfalse
を返します。あなたはまた、単一の関数で全体を包むことができhere
dbfiddle
...
unnest(string_to_array($1, ' '))
分割ワードすべてのスペースに。より洗練された定義が可能です。テキスト検索インフラストラクチャを使用できます。この等価で..
select count(*) from regexp_matches(table.blocktext, ' ', 'gi')
が、はるかに速く1:私はあなたの簡単なカウントに代わる、ところで
を:考えてみましょう
SELECT length(table.blocktext) - length(replace(table.blocktext, ' ', ''))
正規表現関数は強力ですが、価格がかかります。そして集約ステップはそれをはるかに高価にします。関連:
私は、これは正規表現でさえ可能だとは思いません。実用的ではありません。しかし、短時間の研究の後では、[フルテキスト検索](https://www.postgresql.org/docs/9.5/static/textsearch-controls.html#TEXTSEARCH-RANKING)でこれを行うことができるようです。 )? –
Tom、ありがとう、私は下のErwinの助けを借りて作業するバージョンを手に入れましたが、それは決して速くないでしょう。私は完全なテキスト検索を使用したことがないので、次にそれについて学びます。フィードバックを投稿していただき、ありがとうございます。 – afropunk