Сортировка MySQL по количеству вхождений
я делаю поиск в двух текстовых полях под названием Subject
и Text
для определенного ключевого слова. Для этого я использую LIKE
заявление. Я столкнулся с проблемой при попытке отсортировать результаты по количеству повторений.
мой поисковый запрос выглядит так:
SELECT * FROM Table WHERE (Text LIKE '%Keyword%' OR Subject LIKE '%Keyword%')
Я попытался добавить оператор count () и отсортировать его по количеству вхождений, но оператор count () просто продолжает возвращать количество строк в моей таблице.
здесь запрос с указанием граф:
SELECT *, COUNT(Text LIKE '%Keyword%') AS cnt FROM News WHERE (Text LIKE '%Keyword%' OR Subject LIKE '%Keyword%') ORDER BY cnt
то, что я ищу, - это то, что возвращает количество совпадений по теме и текстовым столбцам в каждой строке, а затем упорядочивает Результат после наибольшего количества вхождений ключевого слова в каждой строке.
3 ответов
ниже запрос может дать вам нет.вхождений строки появляется в обоих столбцах i.e текст и тема и будет сортировать результаты по критериям, но это не будет хорошей производительностью решения, лучше сортировать результаты на уровне кода приложения
SELECT *,
(LENGTH(`Text`) - LENGTH(REPLACE(`Text`, 'Keyword', ''))) / LENGTH('Keyword')
+
(LENGTH(`Subject`) - LENGTH(REPLACE(`Subject`, 'Keyword', ''))) / LENGTH('Keyword') `occurences`
FROM
`Table`
WHERE (Text LIKE '%Keyword%' OR Subject LIKE '%Keyword%')
ORDER BY `occurences` DESC
Скрипка Демо
предложил @lserni более чистый способ расчета вхождений
SELECT *,
(LENGTH(`Text`) - LENGTH(REPLACE(`Text`, 'test', ''))) / LENGTH('test') `appears_in_text`,
(LENGTH(`Subject`) - LENGTH(REPLACE(`Subject`, 'test', ''))) / LENGTH('test') `appears_in_subject`,
(LENGTH(CONCAT(`Text`,' ',`Subject`)) - LENGTH(REPLACE(CONCAT(`Text`,' ',`Subject`), 'test', ''))) / LENGTH('test') `occurences`
FROM
`Table1`
WHERE (TEXT LIKE '%test%' OR SUBJECT LIKE '%test%')
ORDER BY `occurences` DESC
Скрипка Демо 2
вы хотите SUM
вместо. Count подсчитает, сколько записей имеют ненулевые значения, что означает, что будут подсчитаны все совпадения и несоответствия.
SELECT *, SUM(Text LIKE '%Keyword') AS total_matches
...
ORDER BY total_matches
SUM() подсчитает, сколько булевых истинных результатов производит подобное, которое будет типично для целых чисел, поэтому вы получите результат, подобный 1+1+1+0+1 = 4, вместо 5 не-нулей.
// escape $keyword for mysql
$keyword = strtolower('Keyword');
// now build the query
$query = <<<SQL
SELECT *,
((LENGTH(`Subject`) - LENGTH(REPLACE(LOWER(`Subject`), '{$keyword}', ''))) / LENGTH('{$keyword}')) AS `CountInSubject`,
((LENGTH(`Text`) - LENGTH(REPLACE(LOWER(`Text`), '{$keyword}', ''))) / LENGTH('{$keyword}')) AS `CountInText`
FROM `News`
WHERE (`Text` LIKE '%{$keyword}%' OR `Subject` LIKE '%{$keyword}%')
ORDER BY (`CountInSubject` + `CountInText`) DESC;
SQL;
возвращает количество вхождений в каждом поле и виды на что.
на 'keyword'
должен быть ниже, чтобы это работало. Я не думаю, что это действительно быстро, производительность мудрая, поскольку она должна быть строчными полями, и нет никакого поиска без учета регистра в MySQL afaik.
вы можете индексировать каждый news
элемент (subject
и text
) по словам и хранить в другой таблице с news_id
и отсчет возникновения и после этого спичка против что.