高效查询以查找与基于多行的规则匹配的行
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 发行版中。相关:
我有一个包含捷克语单词(>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 发行版中。相关: