Использование SQL для определения статистики слов в текстовом поле
Недавно я работал над некоторыми функциями поиска базы данных и хотел получить некоторую информацию, например, средние слова на один документ (например, текстовое поле в базе данных). Единственное, что я нашел до сих пор (без обработки на языке выбора вне БД):
SELECT AVG(LENGTH(content) - LENGTH(REPLACE(content, ' ', '')) + 1)
FROM documents
Это похоже на работу *, но есть ли у вас другие предложения? В настоящее время я использую MySQL 4 (надеюсь, скоро перейдем к версии 5 для этого приложения), но я также заинтересован в общих решениях.
Спасибо!
* Я могу представить, что это довольно грубый способ определить это, поскольку он не учитывает HTML в контенте и тому подобное. Это нормально для этого конкретного проекта, но опять же есть пути лучше?
Обновление:. Чтобы определить, что я имею в виду под "лучше": более точный, более эффективный или более "правильный" (простой в обслуживании, хорошая практика и т.д.). Для контента, который у меня есть, запрос выше достаточно быстр и является точным для этого проекта, но мне может понадобиться нечто подобное в будущем (поэтому я спросил).
Ответы
Ответ 1
Возможности обработки текста MySQL недостаточно хороши для того, что вы хотите. Сохраненная функция является опцией, но, вероятно, будет медленной. Лучше всего обрабатывать данные в MySQL, чтобы добавить функцию пользовательскую функцию. Если вы все равно собираетесь строить новую версию MySQL, вы также можете добавить родную функцию.
"Правильный" способ заключается в обработке данных вне БД, поскольку базы данных хранятся, а не обрабатываются, и любая тяжелая обработка может накладывать слишком большую нагрузку на СУБД. Кроме того, вычисление подсчета слов вне MySQL упрощает изменение определения того, что считается словом. Как сохранить количество слов в БД и обновить его при изменении документа?
Пример сохраненной функции:
DELIMITER $$
CREATE FUNCTION wordcount(str TEXT)
RETURNS INT
DETERMINISTIC
SQL SECURITY INVOKER
NO SQL
BEGIN
DECLARE wordCnt, idx, maxIdx INT DEFAULT 0;
DECLARE currChar, prevChar BOOL DEFAULT 0;
SET maxIdx=char_length(str);
WHILE idx < maxIdx DO
SET currChar=SUBSTRING(str, idx, 1) RLIKE '[[:alnum:]]';
IF NOT prevChar AND currChar THEN
SET wordCnt=wordCnt+1;
END IF;
SET prevChar=currChar;
SET idx=idx+1;
END WHILE;
RETURN wordCnt;
END
$$
DELIMITER ;
Ответ 2
Это довольно немного быстрее, хотя и немного менее точно. Я обнаружил, что он подсчитал 4% на счетчике, что подходит для сценариев "оценки".
SELECT
ROUND (
(
CHAR_LENGTH(content) - CHAR_LENGTH(REPLACE (content, " ", ""))
)
/ CHAR_LENGTH(" ")
) AS count
FROM documents