Есть ли разница между GROUP BY и DISTINCT

Я узнал кое-что простое о SQL на днях:

SELECT c FROM myTbl GROUP BY C

Имеет тот же результат, что и:

SELECT DISTINCT C FROM myTbl

Что мне интересно, есть ли что-то другое в том, как механизм SQL обрабатывает команду, или это действительно одно и то же?

Я лично предпочитаю четкий синтаксис, но я уверен, что это больше по привычке, чем все остальное.

РЕДАКТИРОВАТЬ: Это не вопрос о агрегатах. Использование GROUP BY с агрегатными функциями понятно.

+285
источник поделиться
27 ответов

Ответ MusiGenesis является функционально правильным в отношении вашего вопроса, как указано; SQL Server достаточно умен, чтобы понять, что если вы используете "Группировать по" и не используете никаких агрегатных функций, то на самом деле вы имеете в виду "Отличительный" - и, следовательно, он генерирует план выполнения, как если бы вы просто использовали "Отличительный" ".

Тем не менее, я думаю, что важно также отметить реакцию Хэнка - кавалерийская обработка "Group By" и "Distinct" может привести к пагубным ошибкам в будущем, если вы не будете осторожны. Не совсем правильно говорить, что это "не вопрос об агрегатах", потому что вы спрашиваете о функциональной разнице между двумя ключевыми словами SQL-запроса, одно из которых предназначено для использования с агрегатами, а другое - нет.

Иногда молоток может вбить винт, но если у вас под рукой есть отвертка, зачем?

(в целях этой аналогии Hammer: Screwdriver :: GroupBy: Distinct и screw => get list of unique values in a table column)

+223
источник

GROUP BY позволяет использовать агрегатные функции, такие как AVG, MAX, MIN, SUM и COUNT. С другой стороны, DISTINCT просто удаляет дубликаты.

Например, если у вас есть куча записей о покупках, и вы хотите знать, сколько было потрачено каждым отделом, вы можете сделать что-то вроде:

SELECT department, SUM(amount) FROM purchases GROUP BY department

Это даст вам одну строку для каждого отдела, содержащую название отдела и сумму всех значений amount во всех строках для этого отдела.

+130
источник
другие ответы

Связанные вопросы


Похожие вопросы

Нет разницы (в SQL Server, по крайней мере). Оба запроса используют один и тот же план выполнения.

http://sqlmag.com/database-performance-tuning/distinct-vs-group

Может быть, есть разница, если есть подзапросы:

http://blog.sqlauthority.com/2007/03/29/sql-server-difference-between-distinct-and-group-by-distinct-vs-group-by/

Нет разницы (стиль Oracle):

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:32961403234212

+42
источник

Используйте DISTINCT, если вы просто хотите удалить дубликаты. Используйте GROUPY BY, если вы хотите применить агрегированные операторы (MAX, SUM, GROUP_CONCAT,... или HAVING).

+32
источник

Какая разница от простой точки зрения для удаления дубликатов

Кроме того, что в отличие от DISTINCT, GROUP BY позволяет агрегировать данные для каждой группы (что было упомянуто многими другими ответами), наиболее важным отличием, на мой взгляд, является тот факт, что две операции "происходят", на двух очень разных этапах логического порядка операций которые выполняются в инструкции SELECT.

Вот наиболее важные операции:

  • FROM (включая JOIN, APPLY и т.д.)
  • WHERE
  • GROUP BY (можно удалить дубликаты)
  • Скопления
  • HAVING
  • Функции окна
  • SELECT
  • DISTINCT (можно удалить дубликаты)
  • UNION, INTERSECT, EXCEPT (можно удалить дубликаты)
  • ORDER BY
  • OFFSET
  • LIMIT

Как вы можете видеть, логический порядок каждой операции влияет на то, что можно сделать с ней и как она влияет на последующие операции. В частности, тот факт, что операция GROUP BY "происходит до" операции SELECT (проекция) означает, что:

  • Это не зависит от проекции (что может быть преимуществом)
  • Он не может использовать никакие значения из проекции (что может быть недостатком)

1. Он не зависит от проекции

Примером, где не в зависимости от проекции, является полезным, если вы хотите рассчитать функции окна на разных значениях:

SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
GROUP BY rating

При запуске в базе данных Sakila это дает:

rating   rn
-----------
G        1
NC-17    2
PG       3
PG-13    4
R        5

То же самое не может быть достигнуто при DISTINCT легко:

SELECT DISTINCT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film

Этот запрос является "неправильным" и дает что-то вроде:

rating   rn
------------
G        1
G        2
G        3
...
G        178
NC-17    179
NC-17    180
...

Это не то, что мы хотели. Операция DISTINCT "происходит после" проекции, поэтому мы больше не можем удалять рейтинги DISTINCT, потому что оконная функция уже была рассчитана и спроецирована. Чтобы использовать DISTINCT, нам нужно было бы вложить эту часть запроса:

SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM (
  SELECT DISTINCT rating FROM film
) f

Боковое примечание: В этом конкретном случае мы могли бы также использовать DENSE_RANK()

SELECT DISTINCT rating, dense_rank() OVER (ORDER BY rating) AS rn
FROM film

2. Он не может использовать никакие значения из проекции

Один из недостатков SQL - это время от времени. По той же причине, что мы видели раньше (а именно, логический порядок операций), мы не можем "легко" группировать то, что мы проектируем.

Это неверно SQL:

SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY name

Это действительно (повторение выражения)

SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY first_name || ' ' || last_name

Это также верно (вложение выражения)

SELECT name
FROM (
  SELECT first_name || ' ' || last_name AS name
  FROM customer
) c
GROUP BY name

Я писал об этой теме более подробно в сообщении в блоге

+31
источник

Я ожидаю, что есть возможность для тонких различий в их исполнении. Я проверил планы выполнения двух функционально эквивалентных запросов в этих строках в Oracle 10g:

core> select sta from zip group by sta;

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    58 |   174 |    44  (19)| 00:00:01 |
|   1 |  HASH GROUP BY     |      |    58 |   174 |    44  (19)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| ZIP  | 42303 |   123K|    38   (6)| 00:00:01 |
---------------------------------------------------------------------------

core> select distinct sta from zip;

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    58 |   174 |    44  (19)| 00:00:01 |
|   1 |  HASH UNIQUE       |      |    58 |   174 |    44  (19)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| ZIP  | 42303 |   123K|    38   (6)| 00:00:01 |
---------------------------------------------------------------------------

Средняя операция немного отличается: "HASH GROUP BY" и "HASH UNIQUE", но сметные затраты и т.д. идентичны. Затем я выполнил их с отслеживанием, и фактические подсчеты операций были одинаковыми для обоих (за исключением того, что второй не должен делать никаких физических чтений из-за кэширования).

Но я думаю, что, поскольку имена операций различны, выполнение будет следовать нескольким другим путям кода и открывает возможность более значительных различий.

Я думаю, вам следует использовать синтаксис DISTINCT для этой цели. Это не просто привычка, она более четко указывает цель запроса.

+19
источник

Для отправленного запроса они идентичны. Но для других запросов, которые могут быть неверными.

Например, это не то же самое, что:

SELECT C FROM myTbl GROUP BY C, D
+14
источник

Я прочитал все вышеприведенные комментарии, но не видел, чтобы кто-то указывал на основное различие между Group By и Distinct, кроме бита агрегации.

Distinct возвращает все строки, а затем де-дублирует их, тогда как Group De дедуплицирует строки, когда они читаются алгоритмом один за другим.

Это означает, что они могут давать разные результаты!

Например, приведенные ниже коды генерируют разные результаты:

SELECT distinct ROW_NUMBER() OVER (ORDER BY Name), Name FROM NamesTable

 SELECT ROW_NUMBER() OVER (ORDER BY Name), Name FROM NamesTable
GROUP BY Name

Если в таблице есть 10 имен, 1 из которых является дубликатом другого, тогда первый запрос возвращает 10 строк, тогда как второй запрос возвращает 9 строк.

Причина в том, что я сказал выше, чтобы они могли вести себя по-другому!

+13
источник

Если вы используете DISTINCT с несколькими столбцами, результирующий набор не будет сгруппирован, как и с GROUP BY, и вы не сможете использовать агрегатные функции с DISTINCT.

+12
источник

Они имеют разную семантику, даже если они имеют эквивалентные результаты по вашим конкретным данным.

+11
источник

Пожалуйста, не используйте GROUP BY, если вы имеете в виду DISTINCT, даже если они работают одинаково. Я предполагаю, что вы пытаетесь сбрить миллисекунды с запросами, и я должен указать, что время разработчика на порядок выше, чем компьютерное время.

+6
источник

GROUP BY имеет очень специфическое значение, которое отличается (heh) от функции DISTINCT.

GROUP BY заставляет результаты запроса группироваться с использованием выбранного выражения, тогда могут быть применены агрегированные функции, и они будут действовать на каждую группу, а не на весь набор результатов.

Вот пример, который может помочь:

Для таблицы, которая выглядит так:

name
------
barry
dave
bill
dave
dave
barry
john

Этот запрос:

SELECT name, count(*) AS count FROM table GROUP BY name;

Будет выводить вывод следующим образом:

name    count
-------------
barry   2
dave    3
bill    1
john    1

Что явно отличается от использования DISTINCT. Если вы хотите сгруппировать свои результаты, используйте GROUP BY, если вам нужен только уникальный список определенного столбца, используйте DISTINCT. Это даст вашей базе данных возможность оптимизировать запрос для ваших нужд.

+5
источник

Если вы используете GROUP BY без какой-либо агрегатной функции, тогда внутренне она будет обрабатываться как DISTINCT, поэтому в этом случае нет разницы между GROUP BY и DISTINCT.

Но когда вам предоставляется предложение DISTINCT, лучше использовать его для поиска ваших уникальных записей, поскольку цель GROUP BY заключается в достижении агрегации.

+5
источник

group by используется в совокупных операциях - например, когда вы хотите получить счет Bs, разбитый столбцом C

select C, count(B) from myTbl group by C

Различный - это то, на что это похоже - вы получаете уникальные строки.

В SQL Server 2005, похоже, оптимизатор запросов может оптимизировать разницу в упрощенных примерах, которые я запускал. Не знаю, если вы можете рассчитывать на это во всех ситуациях.

+4
источник

В этом конкретном запросе нет разницы. Но, конечно, если вы добавите какие-либо совокупные столбцы, вам придется использовать группу.

+3
источник

С точки зрения "SQL язык" две конструкции эквивалентны, и один из них - один из тех вариантов "образа жизни", которые мы все должны сделать. Я думаю, что для DISTINCT есть более четкий пример (и, следовательно, он более внимателен к человеку, который наследует ваш код и т.д.), Но это не значит, что конструкция GROUP BY является недопустимым выбором.

Я думаю, что это "GROUP BY для агрегатов" - это неправильный акцент. Фолк должен знать, что функция set (MAX, MIN, COUNT и т.д.) Может быть опущена, чтобы они могли понять намерение кодера, когда оно есть.

Идеальный оптимизатор распознает эквивалентные SQL-конструкции и всегда будет выбирать идеальный план соответственно. Для вашего реального SQL-сервера по выбору вы должны проверить:)

PS обратите внимание, что положение ключевого слова DISTINCT в предложении select может давать разные результаты, например. контраст:

SELECT COUNT(DISTINCT C) FROM myTbl;

SELECT DISTINCT COUNT(C) FROM myTbl;
+2
источник

В перспективе Teradata:

С точки зрения результирующего набора, не имеет значения, используете ли вы DISTINCT или GROUP BY в Teradata. Набор ответов будет таким же.

С точки зрения производительности, это не то же самое.

Чтобы понять, что влияет на производительность, вам необходимо знать, что происходит с Teradata при выполнении оператора с помощью DISTINCT или GROUP BY.

В случае DISTINCT строки перераспределяются немедленно без какой-либо предварительной агрегации, в то время как в случае GROUP BY на первом шаге выполняется предварительная агрегация, и только после этого уникальные значения перераспределяются по AMP.

Не думайте, что GROUP BY всегда лучше с точки зрения производительности. Когда у вас много разных значений, шаг предварительной агрегации GROUP BY не очень эффективен. Teradata должна отсортировать данные, чтобы удалить дубликаты. В этом случае может быть лучше сначала перераспределить, то есть использовать инструкцию DISTINCT. Только если имеется много повторяющихся значений, оператор GROUP BY, вероятно, является лучшим выбором, поскольку только после выполнения шага дедупликации после перераспределения.

Короче говоря, DISTINCT против GROUP BY в Teradata означает:

GROUP BY → для многих дубликатов DISTINCT → нет или только несколько дубликатов. Иногда при использовании DISTINCT вам не хватает места в буфере на AMP. Причина в том, что перераспределение происходит немедленно, и перекос может привести к тому, что AMP не хватит места.

Если это произойдет, у вас, вероятно, больше шансов с GROUP BY, так как дубликаты уже удалены на первом шаге и меньше данных перемещается через AMP.

+2
источник

Вы только замечаете это, потому что вы выбираете один столбец.

Попробуйте выбрать два поля и посмотреть, что произойдет.

Группа By предназначена для использования следующим образом:

SELECT name, SUM(transaction) FROM myTbl GROUP BY name

Которое будет отображаться сумма всех транзакций для каждого человека.

+1
источник

Я знаю это старое сообщение. Но бывает так, что у меня был запрос, который использовал группу только для того, чтобы возвращать отдельные значения при использовании этого запроса в отчетах о жабе и оракуле, все работает нормально, я имею в виду хорошее время отклика. Когда мы перешли с Oracle 9i на 11g, время ответа в Toad было превосходным, но в отчете было занято около 35 минут, чтобы завершить отчет при использовании предыдущей версии, потребовалось около 5 минут.

Решение заключалось в том, чтобы изменить группу и использовать DISTINCT, и теперь отчет запускается примерно через 30 секунд.

Я надеюсь, что это полезно для кого-то с той же ситуацией.

+1
источник

То, как я всегда понимал это, заключается в том, что использование разных элементов совпадает с группировкой по каждому выбранному вами полю в том порядке, в котором вы их выбрали.

то есть:

select distinct a, b, c from table;

совпадает с:

select a, b, c from table group by a, b, c
0
источник

У меня был этот вопрос раньше, мне нужно добавить три столбца из моей таблицы из 4 миллионов строк (три столбца в один новый столбец новой таблицы), но только разные.

Итак, я запустил мою хранимую процедуру, которая содержит этот запрос методом "group by", и потребовалось 32 минуты. Затем я снова запустил его, но с "отличным" методом, и потребовалось 25 минут.

Это тот же результат, но он был немного быстрее со вторым методом

0
источник

Функциональная эффективность совершенно иная. Если вы хотите выбрать только "возвращаемое значение", за исключением дубликата, лучше использовать отличный, чем группировать по. Поскольку "группировать по" включают (сортировка + удаление), "отличные" включают (удаление)

0
источник

В Hive (HQL) группирование по может выполняться намного быстрее, чем по отдельности, поскольку первое не требует сравнения всех полей в таблице. См. Https://sqlperformance.com/2017/01/t-sql-queries/surprises-assumptions-group-by-distinct.

0
источник

Иногда они могут дать вам одинаковые результаты, но они предназначены для использования в другом смысле/случае. Основное отличие заключается в синтаксисе.

Обратите внимание на пример ниже. DISTINCT используется для фильтрации дублированного набора значений. (6, CS, 9,1) и (1, CS, 5,5) являются двумя различными наборами. Таким образом, DISTINCT будет отображать обе строки, в то время как GROUP BY Branch будет отображать только один набор.

 SELECT * FROM student; 
+------+--------+------+
| Id   | Branch | CGPA |
+------+--------+------+
|    3 | civil  |  7.2 |
|    2 | mech   |  6.3 |
|    6 | cs     |  9.1 |
|    4 | eee    |  8.2 |
|    1 | cs     |  5.5 |
+------+--------+------+
5 rows in set (0.001 sec)

SELECT DISTINCT * FROM student; 
+------+--------+------+
| Id   | Branch | CGPA |
+------+--------+------+
|    3 | civil  |  7.2 |
|    2 | mech   |  6.3 |
|    6 | cs     |  9.1 |
|    4 | eee    |  8.2 |
|    1 | cs     |  5.5 |
+------+--------+------+
5 rows in set (0.001 sec)

SELECT * FROM student GROUP BY Branch;
+------+--------+------+
| Id   | Branch | CGPA |
+------+--------+------+
|    3 | civil  |  7.2 |
|    6 | cs     |  9.1 |
|    4 | eee    |  8.2 |
|    2 | mech   |  6.3 |
+------+--------+------+
4 rows in set (0.001 sec)

Иногда результаты, которые могут быть достигнуты с помощью предложения GROUP BY, не могут быть достигнуты с помощью DISTINCT без использования какого-либо дополнительного предложения или условий. Например, в вышеуказанном случае.

Чтобы получить тот же результат, что и DISTINCT вы должны передать все имена столбцов в предложении GROUP BY, как показано ниже. Итак, посмотрите на синтаксическую разницу. Вы должны знать все имена столбцов, чтобы использовать предложение GROUP BY в этом случае.

SELECT * FROM student GROUP BY Id, Branch, CGPA;
+------+--------+------+
| Id   | Branch | CGPA |
+------+--------+------+
|    1 | cs     |  5.5 |
|    2 | mech   |  6.3 |
|    3 | civil  |  7.2 |
|    4 | eee    |  8.2 |
|    6 | cs     |  9.1 |
+------+--------+------+

Также я заметил, что GROUP BY отображает результаты в порядке возрастания по умолчанию, чего нет у DISTINCT. Но я не уверен в этом. Это может отличаться от поставщика.

Источник: https://dbjpanda.me/dbms/languages/sql/sql-syntax-with-examples#group-by

0
источник

Как правило, мы можем использовать DISTINCT для устранения дубликатов в столбце Specific Column в таблице.

В случае "GROUP BY" мы можем применять функции агрегирования, такие как AVG, MAX, MIN, SUM и COUNT для конкретного столбца и выборки имя столбца и его функция агрегирования приводятся в одном столбце.

Пример:

select  specialColumn,sum(specialColumn) from yourTableName group by specialColumn;
0
источник

С точки зрения использования, GROUP BY используется для группировки тех строк, которые вы хотите вычислить. DISTINCT не будет делать никаких расчетов. В нем не будет повторяющихся строк.

Я всегда использовал DISTINCT, если хочу представить данные без дубликатов.

Если я хочу выполнить расчеты, такие как суммирование общего количества манго, я буду использовать GROUP BY

0
источник

Нет существенной разницы между групповым и отдельным предложением, кроме использования агрегатных функций. Оба они могут использоваться для различения значений, но если в группе с точки зрения производительности лучше. Когда используется определенное ключевое слово, внутри него используется операция сортировки, которая может отображаться в плане выполнения.

Попробуйте простой пример

Объявить таблицу @tmpresult ( Id tinyint )

Вставить в @tmpresult Выберите 5 Союз всех Выберите 2 Союз всех Выберите 3 Союз всех Выберите 4

Выберите отдельный Я бы Из @tmpresult

-1
источник

Посмотрите другие вопросы по меткам или Задайте вопрос