> Какие джойны и группировки используются для подсчета количества людей по адресам (Go)
Уровень: middle · Роль: backend · Язык: Go · Категория: Технические вопросы
Компании: Wildberries
Стек: Go
> Пример ответа
Короткий ответ
Для подсчёта количества людей по адресам используется LEFT JOIN между таблицами людей и адресов, затем GROUP BY по полям адреса и агрегатная функция COUNT(*) или COUNT(people.id). Если нужно учитывать только людей с адресами - INNER JOIN. В Go обычно это оформляется через SQL-запрос в database/sql или ORM (GORM, sqlx).
Подробное объяснение
Основная задача - связать две сущности: людей (users/people) и адреса (addresses). Связь обычно один-ко-многим: один адрес может принадлежать нескольким людям (например, семья), либо один человек имеет один адрес (один-к-одному). В зависимости от модели данных выбирается тип join:
INNER JOIN- вернёт только те записи, где есть соответствие в обеих таблицах. Подходит, если нужно считать только людей с заполненными адресами.LEFT JOIN- вернёт всех людей, даже без адреса (тогда адресные поля будутNULL). При подсчёте черезCOUNT(people.id)такие записи не потеряются, но если считатьCOUNT(addresses.id)- они не попадут в результат.RIGHT JOIN- используется редко, если нужно гарантированно вывести все адреса, даже без людей.
Группировка выполняется по полям, которые определяют уникальность адреса: city, street, house, apartment - в зависимости от структуры. Если адрес хранится одной строкой - группировка по ней.
Важно: при использовании GROUP BY все неагрегированные поля в SELECT должны быть включены в GROUP BY. Иначе SQLite/PostgreSQL/MySQL выдадут ошибку или непредсказуемый результат.
На практике
В Go запрос обычно выполняется через database/sql с подготовленными statements. Если используется GORM, можно построить запрос через цепочку методов: Model(&User{}).Select("addresses.city, COUNT(*) as cnt").Joins("LEFT JOIN addresses ON ...").Group("addresses.city").
Для больших таблиц стоит добавить индексы на внешний ключ (address_id в таблице людей) и на поля группировки. Также полезно использовать COUNT(DISTINCT ...), если нужно исключить дубликаты.
Пример кода
GOtype AddressCount struct {City stringCount int}func CountPeopleByCity(db *sql.DB) ([]AddressCount, error) {query := `SELECT a.city, COUNT(p.id) as cntFROM people pLEFT JOIN addresses a ON p.address_id = a.idGROUP BY a.cityORDER BY cnt DESC`rows, err := db.Query(query)if err != nil {return nil, err}defer rows.Close()var result []AddressCountfor rows.Next() {var ac AddressCountif err := rows.Scan(&ac.City, &ac.Count); err != nil {return nil, err}result = append(result, ac)}return result, rows.Err()}
Как отвечать на собеседовании
Начни с уточнения модели данных: связь между таблицами, наличие внешних ключей. Затем опиши выбор join в зависимости от бизнес-требований: нужны ли люди без адресов. Обязательно упомяни группировку и агрегацию, а также нюанс с COUNT(*) vs COUNT(column) - второй вариант игнорирует NULL. Покажи понимание, что в Go это просто строка SQL, и приведи пример с database/sql или ORM. Если спросят про производительность - упомяни индексы и EXPLAIN.
Что проверяет интервьюер
- Понимание типов join и их различий.
- Умение корректно использовать
GROUP BYс агрегатными функциями. - Знание особенностей
COUNTсNULL. - Практический опыт написания SQL-запросов в Go.
- Понимание модели данных и связей между таблицами.
Типичные ошибки
- Использование
COUNT(*)приLEFT JOIN- посчитает и людей без адресов, но если вSELECTесть поля адреса, они будутNULL, и группировка по ним создаст отдельную группу сNULL. - Забывают включить все неагрегированные поля в
GROUP BY. - Путают
LEFT JOINиINNER JOINпри подсчёте - результат может отличаться. - Не учитывают, что
COUNT(addresses.id)приLEFT JOINвернёт 0 для людей без адреса, аCOUNT(people.id)- 1. - В Go забывают закрывать
rowsчерезdefer rows.Close()или не проверяютrows.Err()после итерации.
> Похожие задачи по Go
Как масштабировать Kafka при высокой нагрузке
Как разделить большую таблицу по студентам для оптимизации запросов
Какие типы записей существуют в DNS
Какой статус у продукта
> Похожие задачи по backend
Как масштабировать Kafka при высокой нагрузке
Как разделить большую таблицу по студентам для оптимизации запросов
Какие типы записей существуют в DNS
Какой статус у продукта
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью