2009-10-30 4 views
2

У меня есть таблица с содержимым, которые выглядят примерно так:Fuzzy группировка в Postgres

id | title 
------------ 
1 | 5. foo 
2 | 5.foo 
3 | 5. foo* 
4 | bar 
5 | bar* 
6 | baz 
6 | BAZ 

... и так далее. Я хотел бы сгруппировать по заголовкам и игнорировать дополнительные биты. Я знаю, Postgres может это сделать:

SELECT * FROM (
    SELECT regexp_replace(title, '[*.]+$', '') AS title 
    FROM table 
) AS a 
GROUP BY title 

Однако, это довольно просто и получил бы очень громоздким, если бы я пытался предвидеть все возможные варианты. Итак, вопрос в том, существует ли более общий способ создания нечеткой группировки, чем при использовании regexp? Возможно ли это, по крайней мере, не нарушая этого?

Edit: Для того, чтобы уточнить, нет предпочтения какой-либо из вариантов, и это то, что таблица должна выглядеть после группировки:

title 
------ 
5. foo 
bar 
baz 

Т.е., изменения были бы элементы, которые отличаются только по несколько символов или заглавные буквы, и неважно, какие из них остались, пока они сгруппированы.

ответ

3

Для любой группировка должна иметь транзитивное равенство, то есть a ~= b, b ~= c => a ~= c.

Сформулируйте его строго с помощью слов, и мы постараемся его сформулировать, используя SQL.

Например, какая группа должна foo*bar перейдите по ссылке?

Update:

Этот запрос заменяет все без буквенно-цифровых символов с пробелами и возвращает первый заголовок из каждой группы:

SELECT DISTINCT ON (REGEXP_REPLACE(UPPER(title), '[^[:alnum:]]', '', 'g')) title 
FROM (
     VALUES 
     (1, '5. foo'), 
     (2, '5.foo'), 
     (3, '5. foo*'), 
     (4, 'bar'), 
     (5, 'bar*'), 
     (6, 'baz'), 
     (7, 'BAZ') 
     ) rows (id, title) 
+0

В свою группу, так как она недостаточно похожа на другие предметы. Вот почему возникает вопрос о нечеткой группировке: неважно, какой из вариантов заканчивается в группе, просто важно, чтобы они были сгруппированы вообще. – slikts

+0

'Reinis I.': * достаточно похожий * обычно не транзитивен, этот menas он не сгруппирован. Если, скажем, 'foo' достаточно похоже на' for', а 'for' достаточно похоже на' bar', но 'foo' недостаточно похож на' bar', то вы не можете создавать какие-либо группы. – Quassnoi

+0

Я не говорю, что это может быть сделано, я спрашиваю, как обойти это. – slikts

2

В какой-то момент, вы будете иметь, чтобы определить, что делает набор значений принадлежит вместе в группе. Если это слишком сложно, возможно, вам следует запретить и запретить ввод нечетких данных или если вы разрешите его, добавьте столбец, содержащий санированную версию заголовка для использования в операциях группировки.