Перейти к основному содержимому
Перейти к основному содержимому

DISTINCT Оператор

Если указан SELECT DISTINCT, в результате запроса останутся только уникальные строки. Таким образом, из всех наборов полностью совпадающих строк в результате останется только одна строка.

Вы можете указать список колонок, которые должны иметь уникальные значения: SELECT DISTINCT ON (column1, column2,...). Если колонки не указаны, учитываются все из них.

Рассмотрим таблицу:

┌─a─┬─b─┬─c─┐
│ 1 │ 1 │ 1 │
│ 1 │ 1 │ 1 │
│ 2 │ 2 │ 2 │
│ 2 │ 2 │ 2 │
│ 1 │ 1 │ 2 │
│ 1 │ 2 │ 2 │
└───┴───┴───┘

Использование DISTINCT без указания колонок:

SELECT DISTINCT * FROM t1;
┌─a─┬─b─┬─c─┐
│ 1 │ 1 │ 1 │
│ 2 │ 2 │ 2 │
│ 1 │ 1 │ 2 │
│ 1 │ 2 │ 2 │
└───┴───┴───┘

Использование DISTINCT с указанными колонками:

SELECT DISTINCT ON (a,b) * FROM t1;
┌─a─┬─b─┬─c─┐
│ 1 │ 1 │ 1 │
│ 2 │ 2 │ 2 │
│ 1 │ 2 │ 2 │
└───┴───┴───┘

DISTINCT и ORDER BY

ClickHouse поддерживает использование операторов DISTINCT и ORDER BY для различных колонок в одном запросе. Оператор DISTINCT выполняется до оператора ORDER BY.

Рассмотрим таблицу:

┌─a─┬─b─┐
│ 2 │ 1 │
│ 1 │ 2 │
│ 3 │ 3 │
│ 2 │ 4 │
└───┴───┘

Выбор данных:

SELECT DISTINCT a FROM t1 ORDER BY b ASC;
┌─a─┐
│ 2 │
│ 1 │
│ 3 │
└───┘

Выбор данных с другой сортировкой:

SELECT DISTINCT a FROM t1 ORDER BY b DESC;
┌─a─┐
│ 3 │
│ 1 │
│ 2 │
└───┘

Строка 2, 4 была отсеяна перед сортировкой.

Учитывайте эту специфику реализации при программировании запросов.

Обработка NULL

DISTINCT работает с NULL так, как будто NULL является определённым значением, и NULL==NULL. Другими словами, в результатах DISTINCT разные комбинации с NULL встречаются только один раз. Это отличается от обработки NULL в большинстве других контекстов.

Альтернативы

Можно получить тот же результат, применяя GROUP BY к тому же набору значений, что указаны в операторе SELECT, без использования каких-либо агрегатных функций. Но есть несколько отличий от подхода GROUP BY:

  • DISTINCT может применяться вместе с GROUP BY.
  • Когда ORDER BY опущен и определён LIMIT, выполнение запроса прекращается сразу после того, как читается необходимое количество различных строк.
  • Блоки данных выводятся по мере их обработки, без ожидания завершения всего выполнения запроса.