📘 Условие
У тебя есть две таблицы:
users(id, name)
posts(id, user_id, title)
Вопрос:
Выведи всех пользователей, у которых нет ни одного поста,
а также пользователя, у которого больше всего постов.
📌 Но — в одном запросе.
❓ Попробуй решить задачу таким SQL:
SELECT u.name, COUNT(p.id) AS post_count
FROM users u
LEFT JOIN posts p ON u.id = p.user_id
GROUP BY u.name
HAVING COUNT(p.id) = 0 OR COUNT(p.id) = (
SELECT MAX(cnt)
FROM (
SELECT COUNT(*) AS cnt
FROM posts
GROUP BY user_id
) t
);
🔍 Вопрос:
1) Почему он может вернуть неправильный результат?
2) В чём разница между
COUNT(*) и COUNT(p.id)? 3) Как переписать его правильно?
✅ Разбор подвоха
💣 Подвох 1:
COUNT(p.id) пропускает NULLКогда ты делаешь
LEFT JOIN, для пользователей без постов p.id = NULL.•
COUNT(*) считает все строки (включая NULL) •
COUNT(p.id) не считает строки, где p.id IS NULL👉 Это может привести к тому, что:
•
COUNT(p.id) = 0 — действительно "нет постов" • но в подзапросе
SELECT COUNT(*) считает иначе и даёт искаженную MAX(cnt)🔁 Как правильно:
1) Подзапрос должен использовать
COUNT(p.id), чтобы сравнение было честным 2) Либо использовать
JOIN вместо LEFT JOIN в подзапросе, чтобы не попасть на "нулевых" пользователей✅ Финальный корректный запрос:
SELECT u.name, COUNT(p.id) AS post_count
FROM users u
LEFT JOIN posts p ON u.id = p.user_id
GROUP BY u.name
HAVING COUNT(p.id) = 0
OR COUNT(p.id) = (
SELECT MAX(cnt)
FROM (
SELECT user_id, COUNT(p.id) AS cnt
FROM posts
GROUP BY user_id
) AS ranked
);
🎯 Такой запрос честно покажет:
• Всех “молчунов” (0 постов)
• И самого активного автора (макс постов)
📌 Отлично подходит для собеседования или тех, кто считает, что "GROUP BY — это просто".
@sqlhub