Вопрос:
Я пишу функцию PostgreSQL для подсчета количества раз, когда определенная текстовая подстрока встречается в другом фрагменте текста. Например, вызов count (‘foobarbaz’, ‘ba’) должен возвращать 2.
Я понимаю, что для проверки наличия подстроки я использую условие, подобное приведенному ниже:
WHERE ‘foobarbaz’ like ‘%ba%’
Однако мне нужно, чтобы он возвращал 2 для количества раз “ba”. Как я могу продолжить?
Заранее благодарим за помощь.
Лучший ответ:
Я бы настоятельно рекомендовал проверить этот ответ, который я отправил в “Как вы считаете появление привязанной строки с помощью PostgreSQL?” . Было показано, что выбранный ответ был значительно медленнее, чем адаптированный вариант regexp_replace(). Накладные расходы на создание строк и запуск агрегата просто слишком высоки.
Самый быстрый способ сделать это следующий:
SELECT (length(str) — length(replace(str, replacestr, »)) )::int / length(replacestr) FROM ( VALUES (‘foobarbaz’, ‘ba’) ) AS t(str, replacestr);
Здесь мы
- Возьмите длину строки, L1
- Вычесть из L1 длину строки со всеми удаленными заменами L2, чтобы получить L3 разницу в длине строки.
- Разделите L3 на длину замены, чтобы получить вхождения
Для сравнения: в пять раз быстрее, чем метод использования regexp_matches(), который выглядит следующим образом.
SELECT count(*) FROM ( VALUES (‘foobarbaz’, ‘ba’) ) AS t(str, replacestr) CROSS JOIN LATERAL regexp_matches(str, replacestr, ‘g’); Ответ №1
Как использовать регулярное выражение:
SELECT count(*) FROM regexp_matches(‘foobarbaz’, ‘ba’, ‘g’);
Флаг ‘g’ повторяет несколько совпадений строки (а не только первой).
Ответ №2
Существует
str_count( src, occurence )
на основе
SELECT (length( str ) — length(replace( str, occurrence, » ))) / length( occurence )
и a
str_countm( src, regexp )
на основе упомянутого @MikeT
SELECT count(*) FROM regexp_matches( str, regexp, ‘g’)
можно найти здесь: postgres-utils
Ответ №3
Попробуйте:
SELECT array_length (string_to_array (‘1524215121518546516323203210856879’, ‘1’), 1) — 1 —RESULT: 7