Как извлечь n-е слово и посчитать вхождения слов в строке MySQL?
Мне нужен запрос mysql:
select <second word in text> word, count(*) from table group by word;
Все примеры регулярных выражений в mysql используются для запроса, если текст соответствует выражению, но не для извлечения текста из выражения. Есть ли такой синтаксис?
Ответы
Ответ 1
Ниже приводится предлагаемое решение для конкретной задачи OP (извлечение 2-го слова строки), но следует отметить, что, поскольку состояния ответа mc0e, фактическое извлечение совпадений регулярных выражений не поддерживается из-за-коробки в MySQL. Если вам это действительно нужно, ваши варианты в основном состоят в том, чтобы: 1) сделать это в пост-обработке на клиенте или 2) установить расширение MySQL для его поддержки.
BenWells имеет это почти правильно. Работая с его кодом, здесь немного скорректированная версия:
SUBSTRING(
sentence,
LOCATE(' ', sentence) + CHAR_LENGTH(' '),
LOCATE(' ', sentence,
( LOCATE(' ', sentence) + 1 ) - ( LOCATE(' ', sentence) + CHAR_LENGTH(' ') )
)
В качестве рабочего примера я использовал:
SELECT SUBSTRING(
sentence,
LOCATE(' ', sentence) + CHAR_LENGTH(' '),
LOCATE(' ', sentence,
( LOCATE(' ', sentence) + 1 ) - ( LOCATE(' ', sentence) + CHAR_LENGTH(' ') )
) as string
FROM (SELECT 'THIS IS A TEST' AS sentence) temp
Это успешно извлекает слово IS
Ответ 2
Более короткая опция для извлечения второго слова в предложении:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('THIS IS A TEST', ' ', 2), ' ', -1) as FoundText
Документы MySQL для SUBSTRING_INDEX
Ответ 3
В соответствии с http://dev.mysql.com/ функция SUBSTRING использует начальную позицию, тогда длина, следовательно, функция для второго слова будет:
SUBSTRING(sentence,LOCATE(' ',sentence),(LOCATE(' ',LOCATE(' ',sentence))-LOCATE(' ',sentence)))
Ответ 4
Нет, нет синтаксиса для извлечения текста с использованием регулярных выражений. Вы должны использовать обычные функции обработки строк.
Альтернативно выберите все значение из базы данных (или первых n символов, если вас беспокоит слишком большая передача данных), а затем используйте регулярное выражение на клиенте.
Ответ 5
Как говорили другие, mysql не предоставляет инструменты regex для извлечения подстроки. Это не значит, что вы не можете их использовать, если вы готовы расширить mysql с помощью пользовательских функций:
https://github.com/mysqludf/lib_mysqludf_preg
Это может быть не очень полезно, если вы хотите распространять свое программное обеспечение, являясь препятствием для установки вашего программного обеспечения, но для внутреннего решения это может быть уместно.
Ответ 6
Я использовал ответ Брендана Буллена как отправную точку для аналогичной проблемы, которую я имел, чтобы извлечь значение определенного поля в строке JSON. Однако, как я прокомментировал его ответ, это не совсем точно. Если ваша левая граница - это не просто пространство, как в исходном вопросе, то расхождение увеличивается.
Исправленное решение:
SUBSTRING(
sentence,
LOCATE(' ', sentence) + 1,
LOCATE(' ', sentence, (LOCATE(' ', sentence) + 1)) - LOCATE(' ', sentence) - 1
)
Два отличия: +1 в индексе индекса SUBSTRING и -1 в параметре длины.
Для более общего решения "найти первое вхождение строки между двумя предоставленными границами":
SUBSTRING(
haystack,
LOCATE('<leftBoundary>', haystack) + CHAR_LENGTH('<leftBoundary>'),
LOCATE(
'<rightBoundary>',
haystack,
LOCATE('<leftBoundary>', haystack) + CHAR_LENGTH('<leftBoundary>')
)
- (LOCATE('<leftBoundary>', haystack) + CHAR_LENGTH('<leftBoundary>'))
)
Ответ 7
Я не думаю, что это возможно. Вы можете использовать функцию SUBSTRING
чтобы извлечь SUBSTRING
часть.
Ответ 8
Моя доморощенная функция замены регулярного выражения может быть использована для этого.
демонстрация
Посмотрите эту демонстрацию DB-Fiddle, которая возвращает второе слово ("I") из известного сонета и количество его появлений (1).
SQL
Предполагая, что используется MySQL 8 или более поздней версии (чтобы разрешить использование общего табличного выражения), следующее вернет второе слово и количество его вхождений:
WITH cte AS (
SELECT digits.idx,
SUBSTRING_INDEX(SUBSTRING_INDEX(words, '~', digits.idx + 1), '~', -1) word
FROM
(SELECT reg_replace(UPPER(txt),
'[^''a-zA-Z-]+',
'~',
TRUE,
1,
0) AS words
FROM tbl) delimited
INNER JOIN
(SELECT @row := @row + 1 as idx FROM
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t1,
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t2,
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t3,
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t4,
(SELECT @row := -1) t5) digits
ON LENGTH(REPLACE(words, '~' , '')) <= LENGTH(words) - digits.idx)
SELECT c.word,
subq.occurrences
FROM cte c
LEFT JOIN (
SELECT word,
COUNT(*) AS occurrences
FROM cte
GROUP BY word
) subq
ON c.word = subq.word
WHERE idx = 1; /* idx is zero-based so 1 here gets the second word */
объяснение
В вышеприведенном SQL используется несколько приемов, и требуется некоторая аккредитация. Во-первых, заменитель регулярного выражения используется для замены всех непрерывных блоков несловарных символов, каждый из которых заменяется одним символом тильды (~
). Примечание. Вместо этого можно выбрать другой символ, если в тексте есть вероятность появления тильды.
Техника из этого ответа затем используется для преобразования строки с разделенными значениями в отдельные значения строки. В сочетании с умным приемом из этого ответа он сгенерировал таблицу, состоящую из последовательности возрастающих чисел: в данном случае 0 - 10000.
Ответ 9
Значение поля:
"- DE-HEB 20% - DTopTen 1.2%"
SELECT ....
SUBSTRING_INDEX(SUBSTRING_INDEX(DesctosAplicados, 'DE-HEB ', -1), '-', 1) DE-HEB ,
SUBSTRING_INDEX(SUBSTRING_INDEX(DesctosAplicados, 'DTopTen ', -1), '-', 1) DTopTen ,
FROM TABLA
Результат:
DE-HEB DTopTEn
20% 1.2%