Это случай реляционного деления .
Предполагая таблицу из 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[])
дБ <> скрипка здесь
Связанные:
Текстовый поиск операторы и индексы могут представлять интерес. Но сначала вам понадобится чешский стеммер, который не включен в стандартный дистрибутив Postgres. Похожие: