Собесов

SQL: средняя оценка по всем отзывам с округлением до 2 знаков

SQLАгрегация и округлениеЛёгкаяJunior

Условие

Есть таблица reviews (review_id, enroll_id, rating INT 1–5, review_date).

Напишите запрос, который выведет среднюю оценку по всем отзывам, округлённую до 2 знаков после запятой.

PostgreSQL 15.5.

Решение

Подход

AVG(rating) посчитает среднее. PostgreSQL вернёт numeric (если ratingINTEGER, среднее уже будет numeric с большим числом знаков). Применяем ROUND(..., 2).

Реализация

SELECT ROUND(AVG(rating)::numeric, 2) AS avg_rating
FROM reviews;

Почему ::numeric

ROUND(double precision, int) в PostgreSQL не существует в этой сигнатуре — есть ROUND(numeric, int) (с точностью) и ROUND(double precision) (без). Поэтому нужно явно привести AVG к numeric.

-- Это упадёт с ошибкой: function round(double precision, integer) does not exist
SELECT ROUND(AVG(rating), 2) FROM reviews;
 
-- Правильно:
SELECT ROUND(AVG(rating)::numeric, 2) FROM reviews;
 
-- Альтернатива:
SELECT ROUND(CAST(AVG(rating) AS numeric), 2) FROM reviews;

Сложность

O(n) — один проход по таблице. Индекс не нужен.

Подводные камни

  1. ROUND(AVG(rating), 2) без cast. В PostgreSQL даст ошибку. В MySQL/SQL Server — сработает, но запрос не будет переносим.
  2. AVG игнорирует NULL. Если в rating есть NULL-ы (не должно быть по схеме, но мало ли), они выпадут из числителя и знаменателя. Чтобы засчитать NULL как 0: AVG(COALESCE(rating, 0)).
  3. Деление целых. SUM(rating) / COUNT(*) — если оба INTEGER, получите целочисленное деление (12 / 5 = 2, а не 2.4). AVG сразу возвращает numeric/double.
  4. Округление банкира. PostgreSQL ROUND для numeric использует «half away from zero» (стандартное), для double precision — «half to even». В этой задаче для rating 1–5 различий не будет.

Эталонный ответ

SELECT ROUND(AVG(rating)::numeric, 2) AS avg_rating
FROM reviews;

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти