Булева логика и фильтры: вопросы для собеседования (часть 4)

AND, OR, NOT, законы де Моргана, приоритет операторов — булева логика лежит в основе фильтрации данных в SQL и Python. На собеседовании дают сложное условие с вложенными AND/OR и просят определить, какие строки пройдут фильтр. Ошибки в логических выражениях — одна из самых частых причин неправильных результатов.

Качество данных и инвариантыВоронки и когортные рассужденияJOIN и кардинальностьПостановка задачиДоли и процентыSanity-check и оценкаСегментация и конфаундингТеория множеств и дедупликацияВзвешенные средние и смешение

Вопросы 1620 из 20

16Нужно оставить только внешних пользователей: исключить тех, у кого `is_internal = 1` или `is_bot = 1`. Какой фильтр корректен?
A`NOT (is_internal = 1) OR NOT (is_bot = 1)`
B`is_internal = 0 OR is_bot = 0`
C`NOT (is_internal = 1 AND is_bot = 1)`
D`NOT (is_internal = 1 OR is_bot = 1)`
Ответ: Если плохая группа задана как `is_internal = 1 OR is_bot = 1`, то её исключение записывается как `NOT (is_internal = 1 OR is_bot = 1)`.

Чтобы исключить всех, кто удовлетворяет хотя бы одному из условий, сначала объединяют их через `OR`, а затем берут отрицание всей скобки. По правилу де Моргана это эквивалентно `NOT (is_internal = 1) AND NOT (is_bot = 1)`, что часто читается ещё яснее. Запись `NOT (A) OR NOT (B)` слишком мягкая и оставляет пользователей, у которых выполнено одно из плохих условий. Отрицание `AND` исключает только пересечение, а не объединение.

Подробный разбор →
17В фильтре написали `country = 'RU' AND device = 'ios' OR device = 'android'`. Какой набор строк реально пройдёт фильтр при стандартном приоритете, где `AND` сильнее `OR`?
AТолько строки, где выполняется `country = 'RU' AND (device = 'ios' OR device = 'android')`
BСтроки, где `(country = 'RU' AND device = 'ios') OR device = 'android'`
CТолько строки, где `country = 'RU' AND device = 'android'`
DСтроки, где `country = 'RU' OR (device = 'ios' AND device = 'android')`
Ответ: Без скобок `device = 'android'` становится отдельной веткой через `OR` и не зависит от условия по стране.

Сначала вычисляется часть `country = 'RU' AND device = 'ios'`. Затем результат объединяется с `device = 'android'` через `OR`, поэтому все android-строки попадают в выборку независимо от страны. Это типичная ошибка приоритета: хотели `country = 'RU' AND (device = 'ios' OR device = 'android')`, но забыли скобки. Без скобок `AND` связывается раньше `OR`, и второе устройство «отрывается» от страны.

Подробный разбор →
18В таблице пользователей есть флаги `has_email_optin` и `has_push_optin` (0 или 1). Нужно выбрать пользователей, у которых включён ровно один канал (email или push, но не оба). Какое условие корректно?
A`(has_email_optin = 1 AND NOT (has_push_optin = 1)) OR (NOT (has_email_optin = 1) AND has_push_optin = 1)`
B`has_email_optin = 1 AND has_push_optin = 1`, что выбирает пользователей с обоими включёнными каналами связи
C`has_email_optin = 1 OR has_push_optin = 1`, что выбирает пользователей хотя бы с одним включённым флагом
D`NOT (has_email_optin = 1 AND has_push_optin = 1)`, что отбрасывает только случай с обоими включёнными
Ответ: «Ровно один» — это исключающее «или» (XOR): один флаг истинен, другой ложен.

«Ровно один» — это исключающее «или» (XOR): один флаг истинен, другой ложен. Объединяем два взаимно исключающих случая через `OR`: `(A AND NOT B) OR (NOT A AND B)`. Условие `A AND B` выберет только пользователей с обоими каналами, а `A OR B` — ещё и тех, у кого включены оба. `NOT (A AND B)` пропускает также случай, когда не выполнено ни одно условие.

Подробный разбор →
19Условие в фильтре написали как `(is_paying = 1 AND is_mobile = 1) OR (is_paying = 1 AND NOT (is_mobile = 1))`. Какому условию оно тождественно равно?
A`is_mobile = 1 AND (is_paying = 1 OR is_paying = 0)`
B`is_paying = 1 AND is_mobile = 1` без других условий
C`is_paying = 1 OR is_mobile = 1` без других условий
D`is_paying = 1 AND (is_mobile = 1 OR NOT is_mobile = 1)`
Ответ: Здесь `is_paying = 1` общий для обеих веток, а `is_mobile = 1 OR NOT (is_mobile = 1)` истинно всегда.

Исходное выражение покрывает оба случая для `is_mobile`: когда флаг истинный и когда он ложный, но в обоих случаях требуется `is_paying = 1`. Поэтому объединение двух веток через `OR` не добавляет новых ограничений по `is_mobile`. Упрощение до `is_paying = 1` делает фильтр короче и снижает риск логических ошибок при дальнейших правках.

Подробный разбор →
20Какое выражение эквивалентно условию `is_paying = 1 AND (country = 'RU' OR country = 'KZ')` без изменения смысла?
A`is_paying = 1 AND country = 'RU' OR country = 'KZ'`
B`(is_paying = 1 AND country = 'RU') OR (is_paying = 1 AND country = 'KZ')`
C`(is_paying = 1 OR country = 'RU') AND (is_paying = 1 OR country = 'KZ')`
D`is_paying = 1 OR (country = 'RU' AND country = 'KZ')`
Ответ: Условие `is_paying = 1 AND (country = 'RU' OR country = 'KZ')` можно переписать как `(is_paying = 1 AND country = 'RU') OR (is_paying = 1 AND country = 'KZ')`.

Это полезно, когда вы хотите явно увидеть два сценария, которые приводят к попаданию в сегмент. Важно не потерять скобки, иначе приоритет `AND`/`OR` изменит смысл. Такая форма часто помогает при дебаге, когда нужно понять, какая ветка `OR` сработала для конкретной строки.

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

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

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

Открыть Карьерник в Telegram

Другие темы: Логика

Качество данных и инвариантыВоронки и когортные рассужденияJOIN и кардинальностьПостановка задачиДоли и процентыSanity-check и оценкаСегментация и конфаундингТеория множеств и дедупликацияВзвешенные средние и смешение