高效查询以查找与基于多行的规则匹配的行

Efficient query to find rows matching a rule based on multiple rows

我有一个包含捷克语单词(>100 万行)的 PostgreSQL table,其中有一列名为 "word" [text],我想找到所有偏角相同的单词(参见 Czech declination)基于单词结尾。

例如我想找到所有以 "e" 结尾的单词(例如 kuře),但也存在以 "ete" 结尾的单词形式(例如 kuřete)以及 "etem"(例如 kuřetem)和也 "eti"(例如 kuřeti)。对于每个单词存在大约。 14个单词形式。

找到所有符合规则的单词的有效方法(SQL 查询)是什么?

嗯。 . .如果我理解正确,那么这不是那个有效的操作。但我认为聚合可能是最快的方法,除非你深入研究神秘的索引策略(即使这样也可能行不通):

select left(word, length(word) - 1) || 'e'
from words w
where word ~ '(e|ete|etem)$'
group by left(word, length(word) - 1);

这是一个关系划分的案例。

假设 table 个 UNIQUE 个单词,例如:

CREATE TABLE words (word text PRIMARY KEY);

这应该是最快的解决方案之一:

SELECT w0.stem
FROM  (
   SELECT left(word, -4) AS stem  -- -4 = length('etem')
   FROM   words
   WHERE  word LIKE '%etem'  -- pick the most selective ending to get started
   ) w0
JOIN   words w1 ON w1.word = stem || 'eti'
JOIN   words w2 ON w2.word = stem || 'ete'
JOIN   words w3 ON w3.word = stem || 'e';

查找以所有给定结尾出现的所有词干。更多以相同词干开头和 不同 结尾的单词不会被取消资格!

如果您必须检查多个结尾(14 个?),将所有结尾都拼出来可能会很乏味。较短的代码,通常较慢:

SELECT w0.stem
FROM  (
   SELECT left(word, -4) AS stem
   FROM   words
   WHERE  word LIKE '%etem'  -- pick the most selective ending to get started
   ) w0
CROSS  JOIN unnest ('{eti,ete,e}'::text[]) x(dec)  -- all other in an array
JOIN   words w1 ON w1.word = w0.stem || x.dec
GROUP  BY w0.stem
HAVING count(*) = 3;  -- = cardinality('{eti,ete,e}'::text[])

db<>fiddle here

相关:

  • How to filter SQL results in a has-many-through relation

Text search 运算符和索引可能会感兴趣。但是你首先需要一个捷克语词干分析器,它不包含在标准的 Postgres 发行版中。相关: