Подсчет вхождений слов в столбце таблицы

У меня есть таблица с полем varchar(255). Я хочу получить (с помощью запроса, функции или SP) количество вхождений каждого слова в группе строк из этой таблицы.

Если есть 2 строки с этими полями:

"I like to eat bananas"
"I don't like to eat like a monkey"

я хочу получить

    word | count()
    ---------------
    like  3
    eat   2
    to    2
    i     2
    a     1

Есть идеи? Я использую MySQL 5.2.


person Elad Meidar    schedule 07.07.2009    source источник
comment
Возможный дубликат Подсчитайте частоту каждого слова. Настоящий вопрос старше, но решение было принято в другом вопросе.   -  person RandomSeed    schedule 05.05.2014


Ответы (5)


@Элад Мейдар, мне понравился твой вопрос, и я нашел решение:

SELECT SUM(total_count) as total, value
FROM (

SELECT count(*) AS total_count, REPLACE(REPLACE(REPLACE(x.value,'?',''),'.',''),'!','') as value
FROM (
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(t.sentence, ' ', n.n), ' ', -1) value
  FROM table_name t CROSS JOIN 
(
   SELECT a.N + b.N * 10 + 1 n
     FROM 
    (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
   ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
    ORDER BY n
) n
 WHERE n.n <= 1 + (LENGTH(t.sentence) - LENGTH(REPLACE(t.sentence, ' ', '')))
 ORDER BY value

) AS x
GROUP BY x.value

) AS y
GROUP BY value

Вот полная рабочая скрипка: http://sqlfiddle.com/#!2/17481a/1

Сначала мы делаем запрос для извлечения всех слов, как описано здесь @peterm (следуйте его инструкциям, если вы хотите настроить общее количество обработанных слов). Затем мы преобразуем это в подзапрос, а затем COUNT и GROUP BY значение каждого слова, а затем делаем еще один запрос поверх этого для GROUP BY случаев несгруппированных слов, где могут присутствовать сопровождающие знаки. то есть: привет = привет! с REPLACE

person Gabriel Rodriguez    schedule 23.09.2015

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

person Alex N.    schedule 07.07.2009
comment
Действительно, не разумнее ли запускать его как хранимую процедуру? или функция?. Я всегда думал, что лучше выгружать такие вычисления в БД. - person Elad Meidar; 08.07.2009
comment
Согласен, с помощью обычного SQL это сделать невозможно. Вы можете написать хранимую процедуру для этого, используя временную таблицу и модифицированную версию одного из методов, описанных в этой статье: sommarskog.se/arrays-in-sql-2000.html (это для SQL Server 2000, но его можно довольно легко адаптировать к диалекту MySQL). при этом вы выходите за пределы зоны комфорта SQL - person Ken Keenan; 08.07.2009
comment
Вы, конечно, можете сделать это в SP, используя несколько проходов по набору данных и извлекая каждое слово с помощью регулярного выражения, затем помещая результаты во временную таблицу и выполняя итерацию по ней и так далее. Но это довольно сложно, его будет сложно писать и поддерживать, и я бы сказал, что обслуживание даже важнее, чем его написание. БД хороши для того, для чего они предназначены - хранения/чтения/записи реляционных данных. Заставлять их вычислять вещи — это просто неоптимальный дизайн, который в конечном итоге вернется в виде большого количества PITA. - person Alex N.; 08.07.2009

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

person Community    schedule 08.07.2009
comment
Да, но проблема в том, что мне нужно в области действия пользователя (FK в таблице со строкой, которую мне нужно проанализировать), используя таблицу соединений между словом, фразой и пользователем, кажется, что это слишком много, нет? - person Elad Meidar; 09.07.2009

Вы можете попробовать этот немного извращенный способ:

SELECT 
(LENGTH(field) - LENGTH(REPLACE(field, 'word', ''))) / LENGTH('word') AS `count`
ORDER BY `count` DESC

Этот запрос может быть очень медленным. Кроме того, это выглядит довольно некрасиво.

person Slava Popov    schedule 16.02.2010

Я думаю, что вы слишком много пытаетесь сделать с SQL, если все слова находятся в одном поле каждой строки. Я рекомендую выполнять любую обработку/подсчет текста в вашем приложении после того, как вы захватите текстовые поля из базы данных.

person Troggy    schedule 07.07.2009
comment
Действительно, не разумнее ли запускать его как хранимую процедуру? или функция?. Я всегда думал, что лучше выгружать такие вычисления в БД. - person Elad Meidar; 08.07.2009