> Как написать запрос с использованием CTE в SQL (Go)

Уровень: senior · Роль: backend · Категория: Технические вопросы

Компании: Ютека

Стек: Go

> Пример ответа

CTE (Common Table Expression) - это временный именованный набор результатов, который существует в рамках одного запроса. В Go с драйверами PostgreSQL (например, lib/pq или pgx) CTE работает так же, как в чистом SQL.

Пример: допустим, есть таблица orders (id, user_id, amount, created_at) и нужно получить топ-3 пользователей по сумме заказов за последний месяц.

SQL
WITH user_totals AS (
SELECT
user_id,
SUM(amount) AS total_amount
FROM orders
WHERE created_at >= NOW() - INTERVAL '1 month'
GROUP BY user_id
)
SELECT
user_id,
total_amount
FROM user_totals
ORDER BY total_amount DESC
LIMIT 3;

В Go-коде это выглядит так:

GO
import (
"context"
"github.com/jackc/pgx/v5/pgxpool"
)
type UserTotal struct {
UserID int64
Total float64
}
func GetTopUsers(ctx context.Context, pool *pgxpool.Pool) ([]UserTotal, error) {
query := `
WITH user_totals AS (
SELECT
user_id,
SUM(amount) AS total_amount
FROM orders
WHERE created_at >= NOW() - INTERVAL '1 month'
GROUP BY user_id
)
SELECT user_id, total_amount
FROM user_totals
ORDER BY total_amount DESC
LIMIT 3
`
rows, err := pool.Query(ctx, query)
if err != nil {
return nil, err
}
defer rows.Close()
var result []UserTotal
for rows.Next() {
var ut UserTotal
if err := rows.Scan(&ut.UserID, &ut.Total); err != nil {
return nil, err
}
result = append(result, ut)
}
return result, nil
}

Ключевые моменты:

  • CTE улучшает читаемость сложных запросов, разбивая их на логические блоки.

  • В Go запрос передаётся как обычная строка - никаких специальных адаптаций не требуется.

  • CTE может быть рекурсивным (с RECURSIVE), что полезно для иерархических данных (например, дерево категорий).

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью