Для базовых c ASCII букв, таких как AZ (как упомянуто) и (типичная) кодировка UTF-8 или LATIN * (или большинство других):
SELECT chr(c) AS letter
, sum(octet_length(col)
- octet_length(translate(col, chr(c), ''))) AS total_count
FROM generate_series (ascii('A'), ascii('Z')) c
CROSS JOIN tbl
GROUP BY 1;
translate()
работает для односимвольных замен и немного быстрее, чем replace()
- который вы будете использовать для поиска многосимвольных строк.
In ( типично) кодировка UTF-8 или LATIN *, буквы c ASCII представлены одним байтом. Это позволяет более быструю функцию octet_length()
. Для подсчета символов, закодированных большим количеством байтов, вместо этого используйте length()
, который подсчитывает символы вместо байтов.
Кроме того, мы можем удобно генерировать диапазон букв, таких как AZ, с generate_series()
, потому что их байтовое представление выстраивается в непрерывном диапазоне в упомянутых кодировках. Преобразовать в integer
с помощью ascii()
и обратно с chr()
.
Затем CROSS JOIN
к вашему столу (tbl
), измерить разницу между исходной длиной и после удаления буквы интереса и суммой.
Но при подсчете многих символов в ваших строках этот альтернативный подход , вероятно, намного быстрее :
SELECT letter, count(*) AS total_count
FROM tbl, unnest(string_to_array(col, NULL)) letter
WHERE ascii(letter) BETWEEN ascii('A') AND ascii('Z')
GROUP BY 1;
Для подсчета без учета регистра введите lower()
или upper()
:
FROM tbl, unnest(string_to_array(upper(col), NULL)) letter
Чтобы проверить наличие нескольких непостоянных диапазонов символов:
WHERE letter ~ '^[a-zA-Z]$' -- a-z and A-Z separately (case-sensitive)
Или случайный выбор:
WHERE 'abcXYZ' ~ letter
string_to_array()
с разделителем NULL
разбивает строку на массив из отдельных символов, unnest()
(используя неявный CROSS JOIN LATERAL
), отфильтруйте интересующие вас (опять же, используя их байтовое представление, чтобы сделать это быстро. Затем просто посчитайте за символ.
Связанный: