Как обрезать строку в SQL
Карьерник — квиз-тренажёр в Telegram с 1500+ вопросами для собесов аналитика. SQL, Python, A/B, метрики. Бесплатно.
Зачем это нужно
Грязные данные — ежедневная реальность аналитика. В колонке email лежит ' ALICE@example.com ' — с пробелами и в верхнем регистре. Сравнение email = 'alice@example.com' не находит, фильтры ломаются, GROUP BY разделяет одного пользователя на двух.
Обрезка строк — базовый навык. На собеседовании часто просят: «в данных email с пробелами, как найти дубликаты». Правильный ответ: LOWER(TRIM(email)). Не знаете — минус балл.
В статье:
- TRIM / LTRIM / RTRIM — убрать пробелы
- SUBSTRING — взять часть
- LEFT / RIGHT — взять с начала / конца
- LENGTH для проверки
- REPLACE для замены
1. TRIM — убрать пробелы
SELECT TRIM(' hello '); -- 'hello'
SELECT LTRIM(' hello '); -- 'hello ' (только слева)
SELECT RTRIM(' hello '); -- ' hello' (только справа)Убрать конкретный символ:
SELECT TRIM('.' FROM '....hello....'); -- 'hello'
SELECT TRIM(BOTH '#' FROM '##hello##'); -- 'hello'2. SUBSTRING — взять часть
-- с 1-й позиции, 5 символов
SELECT SUBSTRING('hello world', 1, 5); -- 'hello'
-- с 7-й до конца
SELECT SUBSTRING('hello world', 7); -- 'world'
-- альтернативный синтаксис
SELECT SUBSTRING('hello world' FROM 1 FOR 5);3. LEFT / RIGHT
SELECT LEFT('hello world', 5); -- 'hello'
SELECT RIGHT('hello world', 5); -- 'world'4. LENGTH / CHAR_LENGTH
SELECT LENGTH('hello'); -- 5
SELECT LENGTH('привет'); -- 12 (байтах UTF-8) в Postgres
SELECT CHAR_LENGTH('привет'); -- 6 (символов)Для Unicode используйте CHAR_LENGTH.
5. REPLACE
SELECT REPLACE('hello world', 'world', 'SQL'); -- 'hello SQL'
-- убрать все пробелы
SELECT REPLACE(' hello world ', ' ', ''); -- 'helloworld'6. Практика: почистить email
SELECT
email,
LOWER(TRIM(email)) AS clean_email
FROM users;7. Телефон — оставить только цифры
Postgres (regex)
SELECT REGEXP_REPLACE('+7 (495) 123-45-67', '[^0-9]', '', 'g');
-- '74951234567'MySQL
SELECT REGEXP_REPLACE('+7 (495) 123-45-67', '[^0-9]', '');8. Первые N символов
-- SKU с 3 буквами префикса
SELECT LEFT(sku, 3) AS category_code FROM products;9. Убрать «.0» с конца (если число пришло как строка)
SELECT TRIM(TRAILING '.0' FROM '123.0'); -- '123'10. Поиск и замена с условием
-- username без домена
SELECT SUBSTRING(email FROM 1 FOR POSITION('@' IN email) - 1) AS username
FROM users;В разных СУБД
| Функция | Postgres | MySQL | MSSQL | ClickHouse |
|---|---|---|---|---|
| TRIM | TRIM(...) | TRIM(...) | TRIM(...) | trim(...) |
| SUBSTRING | SUBSTRING(s, 1, 5) | SUBSTRING(s, 1, 5) | SUBSTRING(s, 1, 5) | substring(s, 1, 5) |
| LEFT | LEFT(s, n) | LEFT(s, n) | LEFT(s, n) | left(s, n) |
| LENGTH | LENGTH / CHAR_LENGTH | LENGTH / CHAR_LENGTH | LEN(s) | length(s) |
Частые ошибки
1. LENGTH vs CHAR_LENGTH на Unicode
В Postgres LENGTH('я') → 2 (байт), CHAR_LENGTH → 1 (символ). Для русского — CHAR_LENGTH.
2. SUBSTRING индекс с 1
В SQL — с 1. В Python — с 0.
3. Не LOWER + TRIM
Сравнение без нормализации находит меньше. Правильно: LOWER(TRIM(col)).
4. REPLACE последовательный
REPLACE(REPLACE(s, 'a', 'b'), 'b', 'c') — может дать неожиданный результат (a→b, потом b→c, итог c, не b).
Связанные темы
FAQ
TRIM убирает табы и newlines?
По умолчанию только пробелы. Для других — TRIM('\t\n' FROM s).
SUBSTRING с отрицательным индексом?
В Postgres работает (с конца). В MySQL — возможны проблемы.
LEFT(s, 0)?
Пустая строка.
Как ускорить на миллионах?
Индекс на LOWER(TRIM(col)): CREATE INDEX idx ON users(LOWER(TRIM(email))).
Тренируйте SQL — откройте тренажёр с 1500+ вопросами для собесов.