Собесов

SQL — DISTINCT после GROUP BY: сколько строк вернёт запрос

SQLGROUP BY и DISTINCTСредняяMiddle

Условие

SELECT DISTINCT a, b, c, sum(d) AS revenue
FROM table
GROUP BY a, b, c

Сколько строк вернёт данный запрос, если такой же запрос без DISTINCT вернёт 600 строк, а в столбце revenue содержится 117 уникальных значений?

Варианты:

  • a) 483
  • b) 600
  • c) 117
  • d) 561

Решение

Шаг 1. Что делает GROUP BY a, b, c

После GROUP BY a, b, c строки группируются по уникальным комбинациям (a, b, c). Каждая такая комбинация даёт ровно одну строку в результате.

Значит, если запрос без DISTINCT вернул 600 строк, в данных ровно 600 уникальных комбинаций (a, b, c).

Шаг 2. Что добавляет DISTINCT

DISTINCT применяется к выходному набору запроса, в котором есть колонки (a, b, c, revenue).

Поскольку (a, b, c) уже уникальна в выходе после GROUP BY — каждая строка в выходе уникальна по первым трём колонкам. Добавление revenue к этой комбинации не уменьшает уникальность: все строки уже уникальны.

Значит DISTINCT ничего не отсеет — результат те же 600 строк.

Шаг 3. Зачем тогда здесь "117 уникальных значений"

Это отвлекающая информация. Уникальность отдельной колонки revenue (117 значений) не делает строки (a, b, c, revenue) менее уникальными — потому что колонка (a, b, c) уже уникальна сама по себе.

Кандидаты-обманки:

  • 483 = 600 − 117 — на интуицию «вычесть дубли». Неверно.
  • 561 = 600 − 39 — тоже произвольное число.
  • 117 — соответствует количеству уникальных значений revenue, но это не относится к числу строк.

Шаг 4. Формальный аргумент

DISTINCT после GROUP BY a, b, c, sum(d) означает: «оставь уникальные кортежи (a, b, c, sum_d)».

Если в исходном выходе (a, b, c) уникальна (а это так, по определению GROUP BY), то и (a, b, c, sum_d) уникальна тривиально (добавление колонки не может породить дубли).

Поэтому DISTINCT здесь избыточен и не меняет результат.

Иллюстрация на маленьком примере

Пусть есть таблица:

a b c d
1 x k 10
1 x k 5
2 y l 7
3 z m 12
4 w n 12

Без DISTINCT:

SELECT a, b, c, SUM(d) AS revenue FROM t GROUP BY a, b, c;
a b c revenue
1 x k 15
2 y l 7
3 z m 12
4 w n 12

4 строки. Уникальных значений revenue3 (15, 7, 12).

С DISTINCT:

SELECT DISTINCT a, b, c, SUM(d) AS revenue FROM t GROUP BY a, b, c;

Те же 4 строки — потому что они уже уникальны по (a, b, c).

Не 3 (число уникальных revenue), не 4 − 3 = 1.

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

  1. DISTINCT — это про строки целиком, а не про колонку. DISTINCT a, b, c, d оставляет уникальные кортежи (a, b, c, d), а не «уникальные a отдельно от b».
  2. DISTINCT после GROUP BY обычно избыточен. Если выбираем все колонки группировки — DISTINCT ничего не делает. Может быть полезен, если выбираем подмножество (но тогда нужен другой GROUP BY).
  3. Соблазнительные «арифметические» варианты. 600 − 117 = 483 — типичная ловушка для теста. Не вычитайте уникальные значения колонки из числа строк.
  4. DISTINCTGROUP BY по тем же колонкам, если есть агрегаты. Тут особый случай — DISTINCT навешан поверх агрегации.
  5. NULL в DISTINCT. Если бы в (a, b, c) могли быть NULL, поведение зависит от диалекта (но в большинстве NULL = NULL для DISTINCT). К нашему ответу это не относится.

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

b) 600.

GROUP BY a, b, c уже гарантирует уникальность кортежей (a, b, c) в выходе, поэтому добавление DISTINCT поверх результата не отсеивает ни одной строки.

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

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

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