Условие
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 строки. Уникальных значений revenue — 3 (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.
Подводные камни
- DISTINCT — это про строки целиком, а не про колонку.
DISTINCT a, b, c, dоставляет уникальные кортежи(a, b, c, d), а не «уникальныеaотдельно отb». - DISTINCT после GROUP BY обычно избыточен. Если выбираем все колонки группировки —
DISTINCTничего не делает. Может быть полезен, если выбираем подмножество (но тогда нужен другойGROUP BY). - Соблазнительные «арифметические» варианты.
600 − 117 = 483— типичная ловушка для теста. Не вычитайте уникальные значения колонки из числа строк. DISTINCT≠GROUP BYпо тем же колонкам, если есть агрегаты. Тут особый случай —DISTINCTнавешан поверх агрегации.- NULL в DISTINCT. Если бы в
(a, b, c)могли бытьNULL, поведение зависит от диалекта (но в большинствеNULL = NULLдля DISTINCT). К нашему ответу это не относится.
Эталонный ответ
b) 600.
GROUP BY a, b, c уже гарантирует уникальность кортежей (a, b, c) в выходе, поэтому добавление DISTINCT поверх результата не отсеивает ни одной строки.