> Как написать запрос, который выберет названия всех книг с более чем тремя авторами (Go)
Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы
Компании: Ozon
Стек: Go
> Пример ответа
Короткий ответ
Нужно сгруппировать записи по книге, посчитать количество авторов через COUNT и отфильтровать группы через HAVING. В зависимости от схемы - либо GROUP BY book_id HAVING COUNT(author_id) > 3, либо, если авторы хранятся в JSON-массиве, использовать json_array_length. В PostgreSQL с нормализованной схемой (таблицы books, authors, book_authors) запрос будет выглядеть как SELECT b.title FROM books b JOIN book_authors ba ON b.id = ba.book_id GROUP BY b.id, b.title HAVING COUNT(ba.author_id) > 3.
Подробное объяснение
Ключевая идея - агрегация с фильтрацией групп. WHERE фильтрует строки до группировки, поэтому для условия "более трёх авторов" он не подходит - нужно сначала посчитать количество авторов на каждую книгу, а затем отфильтровать группы. Это делает HAVING.
Схема данных определяет синтаксис. При нормализованной схеме (many-to-many через junction table) группируем по book_id и считаем строки в book_authors. При денормализованной (JSON-массив в колонке authors) - используем json_array_length(authors) > 3 без группировки.
Важный нюанс: если в book_authors возможны дубликаты (например, одна и та же пара книга-автор записана дважды), нужно использовать COUNT(DISTINCT author_id). Также стоит помнить про NULL - если author_id может быть NULL, COUNT его не посчитает, что может исказить результат.
Для PostgreSQL с нормализованной схемой оптимальный индекс - (book_id, author_id) на junction table. Тогда группировка и подсчёт выполняются по индексу без обращения к таблице.
На практике
В реальном проекте с Go и PostgreSQL запрос обычно оборачивается в репозиторий. Типичная ошибка - пытаться использовать WHERE COUNT(*) > 3 вместо HAVING. Также часто забывают про DISTINCT, если модель данных допускает дубликаты.
Если книг с авторами очень много, стоит проверить план выполнения - без индекса на book_id запрос сделает seq scan. В некоторых СУБД (например, MySQL) HAVING можно использовать с алиасами, но в PostgreSQL лучше повторять выражение или использовать GROUP BY по всем выбранным колонкам.
Пример кода
SQL-- Нормализованная схема: books, authors, book_authorsSELECT b.titleFROM books bJOIN book_authors ba ON b.id = ba.book_idGROUP BY b.id, b.titleHAVING COUNT(DISTINCT ba.author_id) > 3;-- Денормализованная схема: колонка authors JSONBSELECT titleFROM booksWHERE json_array_length(authors) > 3;
Как отвечать на собеседовании
Начни с ключевой идеи: GROUP BY + HAVING. Объясни, почему WHERE не подходит - он фильтрует до агрегации. Уточни схему данных, потому что от неё зависит синтаксис. Покажи оба варианта - нормализованный и JSON. Упомяни про COUNT(DISTINCT ...) и индексы. Если спросят про производительность - скажи про индекс (book_id, author_id) и проверку через EXPLAIN.
Что проверяет интервьюер
Проверяется понимание разницы между WHERE и HAVING, умение работать с агрегатными функциями и группировкой. Также оценивается способность адаптировать запрос под схему данных и думать о производительности. Для senior-уровня важно упомянуть edge cases: дубликаты, NULL, индексы.
Типичные ошибки
- Использование
WHERE COUNT(*) > 3- синтаксическая ошибка, агрегаты нельзя использовать вWHERE. - Забывают
GROUP BYпо всем неагрегированным колонкам - в PostgreSQL это приведёт к ошибке, в MySQL может вернуть некорректные данные. - Не учитывают дубликаты в junction table - результат завышается.
- При JSON-схеме пытаются использовать
GROUP BYбез необходимости. - Не проверяют план выполнения на больших таблицах.
> Похожие задачи по Go
Что такое полиморфизм в Go
Как модифицировать архитектуру микросервиса, чтобы обеспечить надежность обработки заказов при падении аналитического сервиса
Какой индекс построить для запроса с условиями на несколько столбцов
Как понять, что код отработал правильно
> Похожие задачи по backend
Что такое полиморфизм в Go
Как модифицировать архитектуру микросервиса, чтобы обеспечить надежность обработки заказов при падении аналитического сервиса
Какой индекс построить для запроса с условиями на несколько столбцов
Как понять, что код отработал правильно
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью