SQLучебникдля начинающихстрокиLIKEregexчасть-9

SQL с нуля. Часть 9: Строки и текст — LIKE, ILIKE, SUBSTRING, regex

2026-06-02 7 мин

Это часть 9 из 10 учебника «SQL с нуля для аналитика». Содержание серии в конце поста. ← Часть 8


TL;DR: LIKE 'pat%' — поиск по подстроке с wildcard (% любая последовательность, _ любой 1 символ). ILIKE — то же без учёта регистра. SUBSTRING(s FROM x FOR y) — обрезка. CONCAT или || — соединение. REGEXP_REPLACE / ~ — regex. Для analytics нужны почти все эти функции.

В этой части:


Как искать по подстроке?

LIKE 'pattern' с двумя wildcard:

-- Email на yandex.ru
SELECT * FROM users WHERE email LIKE '%@yandex.ru';

-- Имена начинающиеся с 'A'
SELECT * FROM users WHERE first_name LIKE 'A%';

-- Имена из 4 букв
SELECT * FROM users WHERE first_name LIKE '____';

-- Любая буква, потом 'van' (Иван, Aван)
SELECT * FROM users WHERE first_name LIKE '_van';

Регистр имеет значение: LIKE 'a%' найдёт 'apple' но не 'Apple'. Для регистронезависимого:

SELECT * FROM users WHERE first_name ILIKE 'a%';   -- PG
SELECT * FROM users WHERE LOWER(first_name) LIKE 'a%';  -- универсально
Типичный кейс: бизнес попросил «всех клиентов из крупных компаний». Через WHERE email LIKE '%@gmail.com' OR email LIKE '%@yandex.ru' ничего не нашли — корпоративные клиенты с personal-доменами. Правильнее — лукап по domain через SPLIT_PART(email, '@', 2) IN (...).

Как обрезать или выделить подстроку?

SUBSTRING(s FROM start FOR length) или короче SUBSTRING(s, start, length):
-- Извлечь домен из email
SELECT
    email,
    SUBSTRING(email FROM POSITION('@' IN email) + 1) AS domain
FROM users;

-- Первые 3 символа
SELECT SUBSTRING(name FROM 1 FOR 3) FROM users;
POSITION('@' IN email) находит позицию символа.

В ClickHouse: substring(s, start, length) — короче синтаксис.

Какие 8 основных строковых функций?

ФункцияЧто делаетПример
LENGTH(s)Длина строкиLENGTH('hello') = 5
UPPER(s)В верхний регистрUPPER('hi') = 'HI'
LOWER(s)В нижнийLOWER('Hi') = 'hi'
TRIM(s)Убрать пробелы по краямTRIM(' hi ') = 'hi'
CONCAT(a, b) или a \\bСоединение'a' \\'b' = 'ab'
REPLACE(s, old, new)ЗаменаREPLACE('abc', 'b', 'X') = 'aXc'
SPLIT_PART(s, delim, n)n-я часть после splitSPLIT_PART('a.b.c', '.', 2) = 'b'
LEFT(s, n) / RIGHT(s, n)Слева/справа N символовLEFT('hello', 3) = 'hel'

Какие типичные задачи аналитика?

Извлечь домен из email

SELECT email, SPLIT_PART(email, '@', 2) AS domain FROM users;

Нормализовать имя (убрать пробелы, в нижний регистр)

SELECT LOWER(TRIM(first_name)) AS normalized_name FROM users;

Соединить имя и фамилию

SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users;
-- или
SELECT first_name || ' ' || last_name FROM users;

Фильтр по части телефона

SELECT * FROM users WHERE phone LIKE '+7%';

Поиск по нескольким маскам

SELECT * FROM products
WHERE name ILIKE '%iphone%' OR name ILIKE '%samsung%';
Типичная задача: «нормализация имён продуктов». LOWER(TRIM(REPLACE(name, ' ', ' '))) приводит " iPhone 15 Pro " → "iphone 15 pro". Дальше можно сравнивать без false-mismatch.

Что такое regex и когда его использовать?

Регулярные выражения — для сложных текстовых паттернов, недоступных LIKE.

В PG — оператор ~ (match) и !~ (не match), регистронезависимые ~* / !~*:

-- Email валидный (упрощённо)
SELECT * FROM users
WHERE email ~ '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$';

-- Имя начинается с заглавной кириллицы
SELECT * FROM users
WHERE first_name ~ '^[А-Я][а-я]+$';

-- Извлечь регион из адреса (например, 'XYZ region 12345' → '12345')
SELECT REGEXP_REPLACE(address, '.*\s(\d+)$', '\1') FROM customers;

Полезные regex-функции PG:

Какие 4 ошибки со строками?

Частые вопросы про строки

LIKE или regex — что быстрее?

LIKE быстрее на простых паттернах ('%text%'). Regex быстрее когда заменяет 5+ OR-условий с LIKE.

Как искать без учёта регистра в MySQL?

COLLATE utf8mb4_general_ci или LOWER(col) LIKE LOWER('pattern').

TEXT или VARCHAR — что брать в PG?

В PG нет разницы по performance. TEXT короче в DDL. Используй TEXT.

Можно ли регулярки в ClickHouse?

Да: match(s, pattern), replaceRegexpOne(s, pat, repl). RE2-диалект.

Как считать символы в UTF-8?

LENGTH('Привет') = 12 (байты в UTF-8). CHAR_LENGTH('Привет') = 6 (символы). Для русского — нужен CHAR_LENGTH.

Что дальше?

В Части 10 — финальная часть. Window Functions intro: ROW_NUMBER, RANK, LAG, LEAD. Самые частые на собесах и в реальной работе.

В Pro — безлимит мок-собесов на AI-интервью + 491 SQL-задача + 612 тестовых заданий + 50+ блог-постов.


Навигация по учебнику

← Часть 8 | Часть 9: Строки и текст | Часть 10 →

Содержание серии: 1 · 2 · 3 · 4 · 5 · 6 · 7 · 8 · 9 · 10

← Вернуться к оглавлению

Источники

SQL-тренажёр
Практика строковых функций на PostgreSQL. 491 задача, первые 5 бесплатно.
Открыть тренажёр →