Булева логика и фильтры: вопросы для собеседования (часть 3)
AND, OR, NOT, законы де Моргана, приоритет операторов — булева логика лежит в основе фильтрации данных в SQL и Python. На собеседовании дают сложное условие с вложенными AND/OR и просят определить, какие строки пройдут фильтр. Ошибки в логических выражениях — одна из самых частых причин неправильных результатов.
Вопросы 11–15 из 20
11Какое условие эквивалентно `NOT (is_paying = 1 AND has_subscription = 1)` по правилу де Моргана? Выберите запись через `OR`.
A`NOT (is_paying = 1) AND NOT (has_subscription = 1)`
B`NOT is_paying = 1 AND has_subscription <> 1`
C`NOT (is_paying = 1) OR NOT (has_subscription = 1)`
D`is_paying = 1 OR has_subscription = 1`
Ответ: По правилу де Моргана `NOT (A AND B)` равносильно `NOT A OR NOT B`.
Чтобы конъюнкция `A AND B` оказалась ложной, достаточно ложности хотя бы одного из условий, поэтому отрицание превращает `AND` в `OR` между отрицаниями частей. Частая ошибка — заменить выражение на `NOT A AND NOT B`: это уже «ни одно из условий», а не «не одновременно оба». Запись через равенство нулю флага и `AND` арифметически совпадает с `NOT A AND NOT B` на бинарных флагах, но логически это другое условие, а не правильное преобразование.
Подробный разбор → 12Сегмент задан условием `is_paying = 1 OR has_trial = 1`. Нужно выбрать пользователей, которые в этот сегмент НЕ входят. Какое условие корректно?
A`NOT (is_paying = 1 OR has_trial = 1)`
B`NOT (is_paying = 1) OR NOT (has_trial = 1)`
C`is_paying = 0 OR has_trial = 0`
D`NOT (is_paying = 1 AND has_trial = 1)`
Ответ: По закону де Моргана отрицание `A OR B` превращается в `NOT A AND NOT B`, что эквивалентно `NOT (A OR B)`.
«Не в сегменте» означает, что не выполняется ни один из двух признаков. Это записывается как `NOT (is_paying = 1 OR has_trial = 1)` или эквивалентно по закону де Моргана: `NOT (is_paying = 1) AND NOT (has_trial = 1)`. Вариант с `OR` между отрицаниями слишком мягкий — он пропустит пользователей, у которых один из признаков всё ещё истинный. Отрицание `AND` сужает условие до тех, у кого выполнено только одно из двух, что тоже неверно.
Подробный разбор → 13Для двух флагов `used_card = 1` и `used_paypal = 1` нужно выбрать пользователей, которые использовали ровно один способ оплаты. Какое условие соответствует этому, используя комбинацию `OR`, `AND` и `NOT` без перечисления двух кейсов?
A`used_card = 1 OR used_paypal = 1` без других дополнительных условий
B`NOT (used_card = 1 OR used_paypal = 1)` без других дополнительных условий
C`(used_card = 1 OR used_paypal = 1) AND NOT (used_card = 1 AND used_paypal = 1)`
D`used_card = 1 AND used_paypal = 1` без других дополнительных условий
Ответ: Условие «ровно один» можно записать как «хотя бы один» `AND` `NOT` «оба одновременно».
Первая часть `(A OR B)` гарантирует, что выполнено хотя бы одно условие. Вторая часть `NOT (A AND B)` запрещает ситуацию, когда истинны оба условия одновременно. В сочетании это даёт ровно один истинный флаг. Такая форма удобна, когда сами условия длинные и их не хочется дублировать в двух ветках. Простое `OR` пропустит и тех, у кого оба флага, а простое `AND` оставит только пересечение.
Подробный разбор → 14Есть условия `is_paying = 1` и `is_active = 1`. Как правильно интерпретировать фильтр `NOT (is_paying = 1 AND is_active = 1)`?
AОставляет строки, где истинно `is_paying = 1 AND is_active = 1`, и исключает остальные комбинации флагов
BОставляет строки, где истинно `NOT (is_paying = 1) AND NOT (is_active = 1)`, и исключает остальные комбинации
CИсключает строки, где оба условия истинны одновременно, и оставляет три остальные комбинации значений флагов
DОставляет строки, где истинно `is_paying = 1 OR is_active = 1`, и исключает только полное отсутствие двух флагов
Ответ: Отрицание `AND` исключает совместное выполнение, но не требует, чтобы оба условия были ложными.
Условие `NOT (A AND B)` означает «не верно, что A и B одновременно». Это включает три случая: A ложно и B истинно, A истинно и B ложно, A ложно и B ложно. Частая ошибка — заменить это на `NOT A AND NOT B`, что соответствует более строгому «ни одно из условий не выполнено». По закону де Моргана `NOT (A AND B) = NOT A OR NOT B`.
Подробный разбор → 15Вы хотите выбрать платящих пользователей из RU или KZ: `is_paying = 1` и страна одна из двух. Какой вариант корректно выражает это без ошибки приоритета `AND`/`OR`?
A`country = 'RU' OR country = 'KZ' AND is_paying = 1`
B`(country = 'RU' OR country = 'KZ') AND is_paying = 1`
C`country = 'RU' AND country = 'KZ' AND is_paying = 1`
D`country = 'RU' OR (country = 'KZ' OR is_paying = 1)`
Ответ: Чтобы блок `country = 'RU' OR country = 'KZ'` не распался, его нужно взять в скобки перед `AND` с `is_paying = 1`.
Без скобок `AND` выполняется раньше `OR`, поэтому `country = 'KZ' AND is_paying = 1` сгруппируется вместе, а `country = 'RU'` станет отдельной веткой `OR`. В результате в выборку попадут все RU пользователи независимо от оплаты. Скобки делают группировку явной и предотвращают типичную ошибку фильтра.
Подробный разбор →