Нечеткая группировка в Postgres

Asked
Viewd1296

2

У меня есть таблица с содержанием, похожим на это:

 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
 

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

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

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

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

2 ответов

3

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

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

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

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

 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)
 

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

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

    slikts30 октября 2009, 17:34
  • Reinis I.: достаточно похожий обычно не является транзитивным, в этом случае его нельзя группировать.Если, скажем, foo достаточно похож на for, а for достаточно похож на bar, но foo недостаточно похож на bar, то вы не можете создавать никакие группы.

    Quassnoi30 октября 2009, 17:37
2

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