2

postgres db には 2 つのテーブルがあります。english_all と english_glob

最初のテーブルには、international、confidential、booting、cooler ...などの単語が含まれています

私は、english_all から単語を取得する関数を作成し、単語ごとに for ループを実行して、anglish_glob テーブルに挿入されていない単語リストを取得しました。単語リストはこんな感じ

I
In
Int
Inte
Inter
..
b
bo
boo
boot
..
c
co
coo
cool
etc..

何らかの理由で、english_all テーブルへの挿入時に zwnj (ゼロ幅の非ジョイナー) が追加されます。しかし、関数では、regexp_replace でその文字を削除しています。

Postgres 関数 for_loop_test は、english_all テーブルから単語を選択していることに基づいて、2 つのパラメーター min と max を取ります。

関数コードは次のようになります

DECLARE
inMinLength ALIAS FOR $1;
inMaxLength ALIAS FOR $2;
mviews RECORD;
outenglishListRow english_word_list;--custom data type eng_id,english_text
BEGIN
FOR mviews IN SELECT id,english_all_text FROM english_all where wlength between inMinLength and inMaxLength 
ORDER BY english_all_text limit 30 LOOP

FOR i IN 1..char_length(regexp_replace(mviews.english_all_text,'(‌)$','')) LOOP
    FOR outenglishListRow IN
        SELECT distinct on (regexp_replace((substring(mviews.english_all_text from 1 for i)),'(‌)$','')) mviews.id,
        regexp_replace((substring(mviews.english_all_text from 1 for i)),'(‌)$','') where 
        regexp_replace((substring(mviews.english_all_text from 1 for i)),'(‌)$','') not 
        in(select english_glob.english_text from english_glob where i=english_glob.wlength)
        order by regexp_replace((substring(mviews.english_all_text from 1 for i)),'(‌)$','')
    LOOP
    RETURN NEXT outenglishListRow;
    END LOOP;


END LOOP;
END LOOP;
END;

単語リストを取得したら、それを別のテーブルenglish_globに挿入します。私の質問は、関数をより効率的にするために関数に追加または削除できるものがあるということです。

編集 english_all テーブルに次のような単語があると仮定しましょう

  • フッター,決済,質問,オーバーフロー,データベース,キングダム

inMinLength = 5 および inmaxLength=7 の場合、外側のループで

  • フッター、定住、王国

選択されます。上記の 3 つの単語の場合、次のような単語を取得するために内側の 2 つのループが適用されます。

  • f、fo、foo、foot、foote、footer、s、se、set、sett、settl ....など。

最終プロセスでは、太字の単語は、適切な単語であることを示す 1 などの別のパラメーターを使用して english_glob に入力され、english_glob テーブルの別のフィールドに格納されます。残りの単語は別のパラメータ 0 で保存されます。次の呼び出しでは、データベースに保存された単語を再度取得する必要がないためです。

edit2: これは完全なコードです

CREATE TABLE english_all
(
id serial NOT NULL,
english_all_text  text NOT NULL,
wlength integer NOT NULL,
CONSTRAINT english_all PRIMARY KEY (id),
CONSTRAINT english_all_kan_text_uq_id UNIQUE (english_all_text)
)

CREATE TABLE english_glob
(
id serial NOT NULL,
english_text  text NOT NULL,
is_prop integer default 1,
CONSTRAINT english_glob PRIMARY KEY (id),
CONSTRAINT english_glob_kan_text_uq_id UNIQUE (english_text)
)

insert into english_all(english_all_text,wlength) values ('ant',char_length('ant')),('forget',char_length('forget')),('forgive',char_length('forgive'));

パラメータ 3 および 6 を使用した関数呼び出しで、後続の行をフェッチする必要があります

a
an
ant
f
fo
for
forg
forge
forget

次は、上記の行に基づいて別のテーブルに挿入されます

insert into english_glob(english_text,is_prop) 
values 
('a',1),('an',1),
('ant',1),('f',0),
('fo',0),('for',1),
('forg',0),('forge',1),
('forget',1),

次回の関数呼び出しでパラメータ 3 と 7 を指定すると、次の行がフェッチされます (f、fo、for、forg はすべて english_glob テーブルに入力されるため)。

forgi
forgiv
forgive

スクリーンショット

4

1 に答える 1

3

次の 1 つのステートメントで実行できます。

SELECT  english_all_text, part,
        part IN
        (
        SELECT  english_text
        FROM    english_glob
        ) AS found
FROM    (
        SELECT  *, SUBSTRING(english_all_text, 1, generate_series(1, LENGTH(english_all_text))) AS part
        FROM    english_all
        WHERE   LENGTH(english_all_text) BETWEEN 5 AND 7
        ) q

確認するサンプル データ:

WITH    english_all(english_all_text) AS
        (
        SELECT  unnest('{footer,settle,question,overflow,database,kingdom}'::text[])
        ),
        english_glob(english_text) AS
        (
        SELECT  unnest('{foot,footer,set}'::text[])
        )
SELECT  english_all_text, part,
        part IN
        (
        SELECT  english_text
        FROM    english_glob
        ) AS found
FROM    (
        SELECT  *, SUBSTRING(english_all_text, 1, generate_series(1, LENGTH(english_all_text))) AS part
        FROM    english_all
        WHERE   LENGTH(english_all_text) BETWEEN 5 AND 7
        ) q

アップデート:

一部がまだリストにない単語を返す必要がある場合は、これを使用します。

SELECT  part
FROM    (
        SELECT  *, SUBSTRING(english_all_text, 1, generate_series(1, LENGTH(english_all_text))) AS part
        FROM    english_all
        WHERE   LENGTH(english_all_text) BETWEEN 5 AND 7
        ) q
WHERE   part NOT IN
        (
        SELECT  english_text
        FROM    english_glob
        )
于 2010-12-30T14:18:38.830 に答える