Недавно мне прислали одну из задач, которую дают на собеседованиях. Делитесь в комментариях, сталкивались ли с подобным - а если у вас есть другие тестовые задания (или интересные кейсы из практики), кидайте в личку! Разберём вместе. 👍
Есть таблица просмотров видео с полями:
user_id - идентификатор пользователя,
video_id - идентификатор видео,
date - дата просмотра.
1 строка - это 1 просмотр видео
Задача: Вывести список пользователей, которые:
✅ Смотрели видео 1 и 3,
❌ Но не смотрели видео 2.
Создадим датафреймчик
data = {
'user_id': [1, 1, 1, 2, 2, 3, 4, 5, 5],
'video_id': [1, 2, 3, 1, 2, 4, 1, 1, 3]
}
df = pd.DataFrame(data)Есть разные способы решения:
Способ 1: Подзапрос с исключением
query = f"""
SELECT user_id
FROM df
WHERE user_id NOT IN (SELECT user_id FROM df WHERE video_id = 2)
GROUP BY user_id
HAVING COUNT(DISTINCT video_id) = 2
result = sqldf(query)
Исключаем пользователей, которые смотрели видео 2.
Оставляем только тех, у кого ровно 2 уникальных просмотра (то есть 1 и 3). Это будет user_id=5
Способ 2: Фильтрация в HAVING
query = f"""
SELECT user_id
FROM df
GROUP BY user_id
HAVING COUNT(*) FILTER (WHERE video_id = 1) > 0
AND COUNT(*) FILTER (WHERE video_id = 3) > 0
AND COUNT(*) FILTER (WHERE video_id = 2) = 0
result = sqldf(query)
Конструкция FILTER (WHERE ...) очень удобна в задачах, где нужно проверить несколько условий одновременно. Просто шик, блеск, красота!
Способ 3 : CASE в HAVING (по сути замена Filter, в MySQL например)
query = f"""
SELECT user_id
FROM df
GROUP BY user_id
HAVING COUNT(CASE WHEN video_id = 1 THEN 1 END) > 0
AND COUNT(CASE WHEN video_id = 3 THEN 1 END) > 0
AND COUNT(CASE WHEN video_id = 2 THEN 1 END) = 0
"""
result = sqldf(query)
Какой способ лучше?
Первый — лаконичный, но это если нет других вариантов video_id.
Второй и третий — более читаемые и гибкие, особенно если нужно добавить дополнительные условия.
P.S. Если хотите добавить что-то своё или знаете альтернативные способы решения — пишите! А если у вас есть похожие задачи — присылайте, сделаем разбор. 💪🤪