Строки и приведение типов: вопросы для собеседования (часть 2)
LIKE, SUBSTRING, CONCAT, TRIM, CAST, регулярные выражения — строковые функции нужны для парсинга и очистки данных. На собеседовании могут попросить извлечь домен из email, привести строку к числу или разобрать URL. Эти задачи проверяют практический опыт работы с «грязными» данными.
Вопросы 6–10 из 20
6В отчёте по городам вы делаете агрегацию по `city`, но видите две строки: `Moscow` и `Moscow ` (с пробелом в конце). Как исправить это прямо в запросе?
AИспользовать `TRIM(city)` и группировать по нему: `SELECT TRIM(city) ... GROUP BY TRIM(city)`.
BПривести к числу: `CAST(city AS int)`.
CДобавить `LIMIT 1`, чтобы осталась одна строка.
DСравнить через `LIKE`: `city LIKE 'Moscow'`.
Ответ: Лишние пробелы часто убирают `TRIM`, особенно перед `GROUP BY` и `JOIN`.
Пробелы в начале/конце строки — частый «мусор» в данных. При `GROUP BY` такие значения считаются разными, поэтому появляются дубликаты групп. `TRIM` нормализует строку и делает агрегацию корректной без ручной чистки таблицы.
7В таблице `products` код товара хранится как текст, например `00123` (важны ведущие нули). Вы хотите соединить её с `catalog(code)` (тоже `text`). Какое действие чаще всего приводит к багу и пропущенным матчам?
AПривести `code` к числу: `CAST(products.code AS int)` или `products.code::int`.
BУбрать пробелы: `TRIM(products.code)`.
CСравнивать как строки: `products.code = catalog.code`.
DНормализовать регистр: `LOWER(products.code)`.
Ответ: Коды с ведущими нулями обычно нужно хранить и сравнивать как текст.
Каст в `int` удаляет ведущие нули: `00123` превращается в 123. После этого сравнение с текстовым `catalog.code` перестаёт находить совпадения. Для таких идентификаторов каст к числу — частый источник скрытых ошибок.
8Вы строите список уникальных email для рассылки и хотите: (1) убрать пробелы по краям, (2) привести все email к нижнему регистру. Какое выражение лучше использовать как нормализованный ключ?
A`TRIM(email)`
B`LOWER(TRIM(email))`
C`LOWER(email)`
D`UPPER(TRIM(email))`
Ответ: Для нормализации строк часто комбинируют `TRIM` и `LOWER`.
Пробелы и разный регистр — два самых частых источника «ложных разных» значений. `LOWER(TRIM(email))` сначала очищает строку от пробелов по краям, а затем приводит к единому регистру. Это делает дедупликацию и сравнения более надежными.
9Поле `age_text` хранится как текст и иногда содержит пробелы, например `18`. Вы хотите отобрать пользователей 18+ через `WHERE`. Какой вариант наиболее корректен?
A`WHERE age_text >= 18`
B`WHERE LOWER(age_text) >= '18'`
C`WHERE CAST(TRIM(age_text) AS int) >= 18`
D`WHERE TRIM(age_text) >= 18`
Ответ: Если сравнение должно быть числовым, приводите к числовому типу после простой очистки строки.
Сравнение строк и чисел либо даст ошибку, либо будет работать не так, как вы ожидаете. Если возраст хранится текстом, надежнее сначала убрать лишние пробелы `TRIM(...)`, а затем привести к `int` через `CAST`. Тогда `WHERE ... >= 18` будет числовым и понятным.
10Вы сделали регистронезависимый `JOIN` по email как `LOWER(u.email) = LOWER(s.email)`, и запрос стал заметно медленнее. Какое объяснение наиболее вероятно на базовом уровне и что обычно делают в аналитических витринах?
A`LOWER` делает сравнение «случайным», поэтому результаты плавают; надо заменить на `UPPER`.
B`JOIN` всегда медленный, и ускорить его нельзя.
CПроблема в том, что `LOWER` меняет тип на `int`; нужно вернуть `text` через `::text`.
DФункция над колонкой усложняет использование индекса/оптимизаций; часто хранят отдельное нормализованное поле (например, `email_lower`) и соединяют уже по нему.
Ответ: Функции в условии соединения могут делать запрос тяжелее; нормализацию часто выносят в отдельное поле.
Нормализовать строки в запросе удобно, но это добавляет вычисления и может ухудшать использование оптимизаций при соединениях. Типичный практичный подход — хранить нормализованное значение (например, email в нижнем регистре) в витрине или материализованном слое и использовать его в `JOIN` и фильтрах.
Хотите тренировать интерактивно?
В приложении — таймер, прогресс, стрики и 1700+ вопросов по всем темам.
Тренировать в Telegram