Теория множеств и дедупликация: вопросы для собеседования (часть 2)
Объединение, пересечение, разность множеств, DISTINCT, дедупликация — базовые операции при работе с данными. На собеседовании просят найти пользователей, которые есть в одной таблице, но отсутствуют в другой, или объяснить, почему UNION и UNION ALL дают разные результаты. Ошибки в дедупликации ведут к двойному подсчёту метрик.
Вопросы 6–10 из 20
6Чтобы посчитать число уникальных пользователей в объединении двух множеств `A` и `B`, зная `|A|`, `|B|` и `|A intersection B|`, какую формулу включения–исключения нужно использовать?
A`|A union B| = |A| + |B| + |A intersection B|`
B`|A union B| = |A| - |B| - |A intersection B|`
C`|A union B| = |A| * |B| / |A intersection B|`
D`|A union B| = |A| + |B| - |A intersection B|`
Ответ: Для двух множеств принцип включения–исключения требует вычесть пересечение, чтобы убрать двойной счёт пересекающихся элементов.
Каждый пользователь из пересечения попадает и в `A`, и в `B`, поэтому при суммировании он считается дважды. Вычитание `|A intersection B|` возвращает правильный размер объединения. Эта формула лежит в основе многих задач про уникальных пользователей по нескольким источникам.
Подробный разбор → 7Вы считаете число покупателей как уникальных пользователей за день. В данных есть `device_id` и `user_id` (если пользователь залогинен). Какой подход к дедупликации обычно более корректен?
AВсегда считать только по `device_id`, потому что устройство гарантирует отсутствие пересечения аудиторий между платформами
BСложить уникальных пользователей по `device_id` и по `user_id`, чтобы получить полное объединение без потери анонимных
CСчитать уникальных по `user_id` там, где он есть, а для анонимных использовать стабильный `device_id`, чтобы не считать дважды
DСчитать уникальных по `order_id`, потому что число заказов за день почти всегда совпадает с числом уникальных покупателей
Ответ: Ключ дедупликации должен соответствовать сущности: для уникальных пользователей это обычно стабильный `user_id`, а не `device_id`.
Если один человек совершает покупку с двух устройств, подсчёт по `device_id` завышает аудиторию и создаёт искусственное пересечение между платформами. Подсчёт по `user_id` ближе к бизнес-смыслу уникального человека, но требует отдельного решения для анонимных. Важно заранее определить, что считается уникальными пользователями, и быть последовательным во всех отчётах, иначе цифры между дашбордами не будут сходиться.
Подробный разбор → 8Аналитик сложил `DAU` за 30 дней и получил 3 млн, а `MAU` за тот же месяц равен 400 тыс уникальных пользователей. Почему это может быть нормально?
A`MAU` равен сумме дневных значений `DAU` за все дни месяца без поправки на повторных пользователей
BСумма `DAU` не делает дедупликацию между днями, а `MAU` это объединение уникальных пользователей за месяц
C`DAU` считает события входа в продукт, а `MAU` считает показы экранов и поэтому стабильно меньше
DПересечение активных пользователей между разными днями строго равно нулю по определению `DAU`
Ответ: Сумма `DAU` по дням повторно считает пересечение пользователей между днями, а `MAU` — это объединение уникальных за месяц.
Один и тот же `user_id` может быть активен много дней подряд и попадает в каждое дневное множество `DAU`. Сложение дневных значений не учитывает пересечение между днями и завышает итог. `MAU` — это дедупликация по `user_id` на уровне месяца, то есть объединение всех дневных множеств. Поэтому сумма `DAU` обычно сильно больше `MAU` — это не ошибка, а следствие повторного учёта.
Подробный разбор → 9У вас есть два источника событий: `web_events` и `app_events`. В каждом вы умеете считать уникальных пользователей по `user_id`. Как корректно получить общее число уникальных пользователей по двум источникам?
AПосчитать `COUNT(DISTINCT user_id)` отдельно в каждом источнике и просто сложить два числа, не учитывая возможное пересечение пользователей между источниками
BПосчитать `COUNT(*)` в обоих источниках и назвать суммарное число числом уникальных пользователей по двум платформам, опираясь на сырое количество строк в таблицах
CВзять только пересечение источников по `user_id` и считать его общим итогом, опираясь на тех пользователей, которые точно есть и в `web_events`, и в `app_events`
DСделать объединение строк из обоих источников по `user_id` и затем посчитать `COUNT(DISTINCT user_id)` для дедупликации повторяющихся записей
Ответ: Если `user_id` может быть и в `web_events`, и в `app_events`, то суммирование двух `COUNT(DISTINCT user_id)` без объединения завышает результат из-за пересечения.
Здесь каждый источник — это множество значений `user_id`, и вам нужен размер их объединения. Самый прямой способ — объединить источники и сделать дедупликацию через `COUNT(DISTINCT user_id)`. Если просто сложить два `COUNT(DISTINCT user_id)`, вы посчитаете пересечение дважды и получите завышение, а пересечение в чистом виде даст заниженное число; `COUNT(*)` по сырым строкам считает события, а не пользователей. Такая проверка адекватности важна для отчётов по аудитории на нескольких платформах.
Подробный разбор → 10В отчёте по кампании указано: множество A имеет 100 тыс уникальных пользователей, множество B имеет 80 тыс уникальных пользователей, а их пересечение равно 120 тыс уникальных пользователей. Какой вывод наиболее корректен?
AОбъединение множеств равно 120 тыс уникальных пользователей: пересечение в данном случае совпадает с объединением
BПересечение между множествами полностью отсутствует: аудитории кампаний A и B не пересекаются по уникальным пользователям
CТак может быть: пересечение превышает каждое из множеств, если один пользователь учитывается несколько раз внутри кампании
DЭто нарушение правил множеств: пересечение не превышает размера любого множества, значит есть ошибка в дедупликации или ключах
Ответ: По правилам теории множеств размер пересечения всегда меньше или равен размеру каждого из множеств.
Если пересечение больше A, значит вы считаете разные сущности или нарушили дедупликацию (например, в одном месте считаете пользователей, а в другом — устройства). Такая проверка адекватности нужна, чтобы быстро обнаружить неверные ключи, дубли после джойнов или смешение единиц учёта. До исправления нельзя интерпретировать ни пересечение, ни объединение. Варианты про равенство объединения 120 тысячам или отсутствие пересечения переворачивают определения; вариант про многократный учёт внутри одной кампании как раз и есть симптом сломанной дедупликации, а не объяснение.
Подробный разбор →