Строки и приведение типов: вопросы для собеседования (часть 3)

LIKE, SUBSTRING, CONCAT, TRIM, CAST, регулярные выражения — строковые функции нужны для парсинга и очистки данных. На собеседовании могут попросить извлечь домен из email, привести строку к числу или разобрать URL. Эти задачи проверяют практический опыт работы с «грязными» данными.

Агрегация, GROUP BY и HAVINGДаты и времяEXPLAIN и оптимизацияВыражения и NULLJOIN и операции множествОсновы SQL-запросовПодзапросы и CTEОконные функции

Вопросы 1115 из 20

11На ревью вы видите выражение `CAST(user_id AS text)` в коде Postgres. Какой вариант с оператором `::` записывает то же самое приведение типа?
A`CAST(user_id text)`
B`user_id AS text`
C`user_id::text`
D`user_id::int::text`
Ответ: `::type` — сокращённая форма явного каста, эквивалентная `CAST(... AS type)`.

В Postgres-подобных СУБД два распространённых синтаксиса явного приведения типов — `CAST(x AS type)` и `x::type`. Оба делают намерение запроса явным и уменьшают риск скрытых проблем из-за неявных приведений. `CAST(user_id text)` без `AS` — синтаксическая ошибка, `user_id AS text` — это алиас, а не приведение, а `user_id::int::text` сначала приводит к `int` и только потом к тексту, что меняет смысл при наличии нечисловых значений.

Подробный разбор →
12У вас есть таблицы `users(email)` и `marketing_signups(email)`. В одной системе email сохраняется как `Ivan@Example.com`, в другой — `ivan@example.com`. Какой подход в `JOIN` чаще всего решает проблему без изменения данных в таблицах?
AСделать `JOIN` как есть: `users.email = marketing_signups.email`, база сама сопоставит регистр.
BСравнивать нормализованные значения: `LOWER(users.email) = LOWER(marketing_signups.email)`.
CСравнивать по длине: `LENGTH(users.email) = LENGTH(marketing_signups.email)`.
DПривести email к числу: `CAST(users.email AS int) = CAST(marketing_signups.email AS int)`.
Ответ: Для регистронезависимого сравнения текст часто нормализуют через `LOWER` или `UPPER` на обеих сторонах.

Сравнение строк в SQL обычно чувствительно к регистру. Если источники данных сохраняют email в разном регистре, прямое сравнение в `JOIN` даст пропуски. Нормализация через `LOWER(...)` на обеих сторонах делает сравнение стабильным и предсказуемым.

Подробный разбор →
13Поле `price_text` хранит цены как текст: `2`, `10`, `100`. Аналитик написал `WHERE price_text > '10'` и получил неожиданный набор строк. Как сделать сравнение числовым?
AОставить как есть и ориентироваться на лексикографическое сравнение строк в `WHERE`
BЗаменить `>` на `LIKE '1%'`, и для текстовых цен это даст корректный отбор по величине
CСделать явное приведение типа: `WHERE CAST(price_text AS int) > 10` для числового сравнения
DИспользовать `WHERE LENGTH(price_text) > 2` как замену числовому сравнению по разрядности
Ответ: Сравнение текстов и чисел — это разные операции: для числовой логики нужно явное приведение типа.

Текст в `WHERE` сравнивается лексикографически, поэтому `'100'` ведёт себя не как число 100, а как строка, начинающаяся с символа `'1'`. Если поле фактически хранит число в виде строки, нужно явно привести его к числовому типу через `CAST(price_text AS int)` или `price_text::int`. Тогда сравнение будет соответствовать бизнес-смыслу. `LIKE` и `LENGTH` сравнивают форму строки, а не её числовое значение, и не дают корректного порядка чисел.

Подробный разбор →
14В таблице событий поле `event_date_text` хранит дату как текст в формате `YYYY-MM-DD`. Вы хотите фильтровать строки за прошлую неделю и группировать по неделе. Что логичнее всего сделать в запросе?
AСравнивать строки напрямую и использовать `LIKE '2025-12-%'` для группировки по периоду
BПривести к типу даты: `CAST(event_date_text AS date)` или `event_date_text::date` для функций дат
CИспользовать `EXTRACT(week FROM event_date_text)` напрямую от строки, не приводя к `date`
DЗаменить дефисы в строке через `REPLACE(event_date_text, '-', '')` для последующей работы
Ответ: Если дальше нужны операции с датами, лучше явно привести текст к типу `date`, а не оставлять строкой.

Даже если строковые даты иногда сравниваются «правильно», это всё равно строковый тип: функции дат, группировки по периодам и проверки корректности формата становятся ненадёжными. Явный каст в `date` через `CAST(... AS date)` или `... ::date` делает логику запроса прозрачной и позволяет использовать `DATE_TRUNC`, `EXTRACT` и арифметику дат. Сравнение строк через `LIKE` хрупко к смене формата, а `EXTRACT` напрямую от текста не работает в большинстве СУБД.

Подробный разбор →
15В поле phone хранится строка из 10 цифр, например 9991234567. Вам нужны первые 3 цифры (код региона) для группировки. Какое выражение подходит?
A`TRIM(phone)`: убирает пробелы по краям строки без выделения нужного префикса
B`SUBSTRING(phone, 1, 3)`: возвращает первые три символа строки `phone` как код региона
C`CAST(phone AS int)`: приводит строку к числовому типу без выделения первых трёх цифр
D`SUBSTRING(phone, 4, 3)`: возвращает три символа начиная с четвёртой позиции, минуя префикс
Ответ: `SUBSTRING(str, 1, n)` берёт первые n символов строки — удобный способ выделить префикс.

Для аналитики часто нужно выделять часть строки: первые символы, кусок по позиции и т.д. В простом случае с фиксированной длиной `SUBSTRING(phone, 1, 3)` вернёт первые 3 символа — код региона. Это удобно для `GROUP BY` и построения срезов. Вариант с позиции 4 берёт уже не код, а следующий блок цифр.

Подробный разбор →
1234

Хотите тренировать интерактивно?

В приложении — таймер, прогресс, стрики и 1700+ вопросов по всем темам.

Тренировать SQL в Telegram

Другие темы: SQL

Агрегация, GROUP BY и HAVINGДаты и времяEXPLAIN и оптимизацияВыражения и NULLJOIN и операции множествОсновы SQL-запросовПодзапросы и CTEОконные функции