<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0">

<channel>

<title>Блог об аналитике, визуализации данных, data science и BI, заметки с тегом: regular expression</title>
<link>http://test.leftjoin.ru/tags/regular-expression/</link>
<description></description>
<generator>E2 (v3365; Aegea)</generator>

<item>
<title>Регулярные выражения как способ решения задач в SQL</title>
<guid isPermaLink="false">127</guid>
<link>http://test.leftjoin.ru/all/sql-regular-expressions/</link>
<comments>http://test.leftjoin.ru/all/sql-regular-expressions/</comments>
<description>
&lt;p&gt;Использование регулярных выражений для выбора определенных ячеек таблицы используется в SQL не так часто, как могло бы. И очень зря — этот инструмент легко позволяет найти в таблице нужные значения, так как использует шаблон для поиска последовательности метасимволов в тексте. Такие задачи встречаются как в различных тренажерах или на собеседованиях на позиции аналитика, так и в реальной практике аналитиков, которые работают в базах SQL. Подобные шаблоны для поиска определенных элементов и последовательностей в тексте используются в самых разных областях. Например, на многих сайтах существует проверка email-адреса, который вы вводите при регистрации, на соответствие стандартному  шаблону.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://test.leftjoin.ru/pictures/email.png.jpg"  border="0" width="100%" height="100%"&gt;&lt;/p&gt;
&lt;p&gt;Как это сделать, мы разберёмся постепенно, а пока давайте начнем с самого начала: с определения.&lt;/p&gt;
&lt;p&gt;&lt;i&gt;Что такое «регулярное выражение»?&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;Регулярное выражение —&lt;/b&gt; последовательность букв и/или символов, которая может встречаться в слове. Например, есть достаточно простое регулярное выражение “bat”. Оно читается как буква b, за которой следует буква a и t, и этому шаблону соответствуют такие слова, как, bat, combat и batalion.&lt;br /&gt;
Давайте разберем несколько типовых задачек, чтобы вам было понятнее, как правильно работать с регулярными выражениями в SQL. Для решения всех задач, которые мы сегодня рассмотрим, мы будем использовать функцию regexp_matches(), которая будет сравнивать значения в ячейках с шаблоном, который задается внутри этой функции.&lt;/p&gt;
&lt;h2&gt;Количество гласных букв в выражении&lt;/h2&gt;
&lt;p&gt;Итак, предположим, вам нужно посчитать количество гласных букв в каждой ячейке определенного столбца таблицы. Именно для такой задачи и нужны регулярные выражения. Код, который приведен ниже (вы можете легко его прогнать в своем SQL), на простом примере показывает, как легко решить эту задачу. В результате, мы получаем еще одну колонку Count, в которой хранится искомая информация.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;with example_table as (select * from (values (1, 'google'), (2, 'yahoo'), (3, 'bing'), (4, 'rambler')) 
as map(id, source_type))

select source_type, count(1) from (
select *, regexp_matches(source_type,'([aeiou])','g') as pattern from example_table ) as t
group by source_type&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Количество согласных букв в выражении&lt;/h2&gt;
&lt;p&gt;Если мы хотим решить обратную задачу, то можно подойти к решению двумя способами. Первый способ — аналогично предыдущему можно перечислить все согласные буквы английского алфавита в квадратных скобках. Но почему бы не решить задачу элегантнее? Для этого есть второй способ — использовать отрицание, то есть посчитать количество всех букв, которые не являются гласными. Для этого используется оператор ^.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;with example_table as (select * from (values (1, 'google'), (2, 'yahoo'), (3, 'bing'), (4, 'rambler')) 
as map(id, source_type))

select source_type, count(1) from (
select *, regexp_matches(source_type,'([^aeiou])','g') as pattern from example_table ) as t
group by source_type&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Количество цифр в выражении равно 3&lt;/h2&gt;
&lt;p&gt;Если нужно найти конкретное число определенных символов в выражении, то в конце запроса нужно указать оператор HAVING.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;with example_table as (select * from (values (1, '1a2s3d'), (2, 'qw12e'), (3, 'q56we1651qwe'), (4, 'qw4e2')) 
as map(id, source_type))

select source_type, COUNT(*) from (
select *, regexp_matches(source_type,'\d','g') as pattern from example_table ) as t
GROUP BY source_type
HAVING COUNT(*) = 3&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;В номере телефона есть два дефиса&lt;/h2&gt;
&lt;p&gt;Теперь давайте перейдем к более конкретным запросам, которые могут пригодиться в реальной практике. Например, у аналитика может стоять задача найти все номера телефона, в которых присутствует два или более дефисов.&lt;br /&gt;
В первом блоке кода мы создаем тестовую таблицу, затем считаем количество дефисов в каждой ячейке (ячейки без дефисов не включаются в финальную таблицу), а после этого проставляем значения True/False относительно условия на количество дефисов. Сделать это можно с помощью оператора CASE WHEN COUNT ().&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;with example_table as (
  select * from (
    values 
    (1, '8931-123-456'), 
    (2, '8931123-456'), 
    (3, '+7812123456'), 
    (4, '8-931-123-42-24')
  )
as map(id, source_type))

select source_type, CASE WHEN COUNT(1) &amp;gt;= 2 THEN 'True' ELSE 'False' END from (
select *, regexp_matches(source_type,'-','g') as pattern from example_table ) as t
GROUP BY 1&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Все имена, которые написаны с большой буквы&lt;/h2&gt;
&lt;p&gt;Тут мы уже приступаем к задаче посложнее: нужно найти имена людей, которые написаны с заглавной буквы со всем датасете. Для этого нам нужно найти все значения, подходящие под заданный шаблон: первая буква слова — заглавная.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;with example_table as (
  select * from (
    values 
    (1, 'alex'), 
    (2, 'Alex'), 
    (3, 'Vasya'), 
    (4, 'petya')
  )
as map(id, source_type))

select source_type from (
select *, regexp_matches(source_type,'^[A-Z]','g') as pattern from example_table ) as t
GROUP BY 1&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Вывести номера телефонов, которые попадают под паттерн +71234564578&lt;/h2&gt;
&lt;p&gt;Последней задачей мы разберем поиск телефонных номеров в списке. Для этого нам нужно найти те значения, которые начинаются со знака “+”, затем идет цифра 7 и 10 любых цифр после этого.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;with example_table as (
  select * from (
    values 
    (1, '+7(931)1234546'), 
    (2, '+79312991809'), 
    (3, '89311234565'), 
    (4, '244-02-38')
  )
as map(id, source_type))

select source_type from (
select *, regexp_matches(source_type,'^\+7[0-9]{10}','g') as pattern from example_table ) as t
GROUP BY 1&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Вывести все настоящие email-адреса&lt;/h2&gt;
&lt;p&gt;Как мы говорили в начале, регулярные выражения могут использоваться для таких задач как поиск сложных выражений по определённому шаблону. На самом деле, ничего особенного в такой задаче нет — главное, грамотно сформировать шаблон выражения и дело в шляпе!&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;with example_table as (
    select * from (
    values
        (1, 'email.asd@ya.ru'),
        (2, 'something@new.ru'),
        (3, '@ya.ru'),
        (4, 'asdasd'),
        (5, '_asdasdasd@mail.ru'),
        (6, 'asd_asdas@mail.ru'),
        (7, '.asdasd@mail.ru'),
        (8, '007asd@email.com')
        ) as map(id, source_type)
)
​
select source_type 
from (
    select source_type, regexp_matches(source_type, '^[^_.0-9][a-z0-9._]+@[a-z]+\.[a-z]+$')
    from example_table ) as t&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Использование регулярных выражений может помочь легко и просто решить достаточно трудные задачи. Пишите в комментариях, если у вас есть какая-то задача по поиску определенных шаблонов в тексте, которая вам никак не дается. Попробуем решить её вместе!&lt;/p&gt;
</description>
<pubDate>Mon, 17 Jan 2022 16:48:16 +0300</pubDate>
</item>


</channel>
</rss>