Вопрос

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

SELECT c FROM myTbl GROUP BY C

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

SELECT DISTINCT C FROM myTbl

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

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

Редактировать:Это не вопрос об агрегатах.Использование GROUP BY с агрегатными функциями все понятно.

Это было полезно?

Решение

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

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

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

(для целей этой аналогии Hammer: Screwdriver :: GroupBy: Distinct и screw = > получить список уникальных значений в столбце таблицы )

Другие советы

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

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

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

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

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

http://sqlmag.com/database-performance-tuning/distinct- против-группа

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

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

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

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

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

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

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

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

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

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

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

Я ожидаю, что есть вероятность незначительных различий в их исполнении. Я проверил планы выполнения для двух функционально эквивалентных запросов по этим направлениям в 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 для этой цели. Это не просто привычка, это более четко указывает на цель запроса.

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

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

SELECT C FROM myTbl GROUP BY C, D

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

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

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

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

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 имен, одно из которых является дубликатом другого, то первый запрос возвращает 10 строк, а второй - 9 строк.

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

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

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

GROUP BY имеет очень специфическое значение, отличное (хе) от функции 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. Это даст вашей базе данных возможность оптимизировать запрос для ваших нужд.

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

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

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

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

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

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

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

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

С точки зрения «языка 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;

В перспективе 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.

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

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

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

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

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

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

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

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

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

т.е.:

select distinct a, b, c from table;

это то же самое , что:

select a, b, c from table group by a, b, c

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

В Hive (HQL) группирование по может выполняться намного быстрее, чем по-разному, поскольку первое не требует сравнения всех полей в таблице. См. https://sqlperformance.com/2017 / 01 / T-SQL-запросы / сюрпризы-допущения-группа по-отчетливый .

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

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

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

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

Выберите разные Я бы Из @tmpresult

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top