На днях я узнал кое-что простое о SQL:
SELECT c FROM myTbl GROUP BY C
Имеет тот же результат, что и:
SELECT DISTINCT C FROM myTbl
Что мне интересно, есть ли что-то другое в способе обработки команды механизмом SQL, или это действительно одно и то же?
Лично я предпочитаю четкий синтаксис, но уверен, что это больше по привычке, чем что-либо еще.
Обновлено: это не вопрос об агрегатах. Понятно использование GROUP BY с агрегатными функциями.
Вы также можете выполнить SELECT c FROM myTbl UNION SELECT c FROM myTbl и получить тот же результат ... Но зачем все усложнять, когда SELECT DISTINCT так просто.
«Логический порядок выполнения» GROUP BY намного раньше, чем «SELECT», а DISTINCT следует за select.
Одно очень незначительное отличие, о котором я не упоминал, заключается в том, что DISTINCT приводит к фактическому выбору поля, то есть значение появится в наборе результатов. GROUP BY может эффективно удалять дубликаты без фактического выбора поля. В большинстве случаев это неактуально, но в других может быть именно то, что вам нужно. Если вы в конечном итоге используете GROUP BY вместо DISTINCT, вероятно, потребуется пояснительный комментарий в коде.
Суть в том, что, поскольку удаление дубликатов происходит в разных точках плана выполнения, одно может быть более эффективным, чем другое, поскольку для удаления дублирования требуется сортировка или, возможно, использование этого индекса по этому индексу. Таким образом, может быть преимущество от раннего удаления дублирования или преимущество может быть получено от использования другого индекса на раннем этапе и использования сортировки позже, когда осталось несколько строк и сортировка незначительна.


У них разная семантика, даже если они дают эквивалентные результаты для ваших конкретных данных.
как это ответ? Простое утверждение, что это разница в семантике, не добавляет никакой информации.
GROUP BY позволяет использовать агрегатные функции, такие как AVG, MAX, MIN, SUM и COUNT.
С другой стороны, DISTINCT просто удаляет дубликаты.
Например, если у вас есть несколько записей о покупках, и вы хотите знать, сколько было потрачено каждым отделом, вы можете сделать что-то вроде:
SELECT department, SUM(amount) FROM purchases GROUP BY department
Это даст вам одну строку для каждого отдела, содержащую название отдела и сумму всех значений amount во всех строках для этого отдела.
Использование GROUP BY Я понимаю, вопрос основан на том факте, что он возвращает отдельный набор данных, когда агрегатная функция отсутствует.
Поскольку GROUP BY неявно выполняет DISTINCT по значениям столбца, по которому вы группируете (извините за какофонию).
Разве нельзя использовать DISTINCT + агрегатные функции? вот так: select distinct department, SUM(amount) from ...
@Sajad, вы можете это сделать, но вам все равно нужно иметь GROUP BY, поэтому DISTINCT ничего за вас не делает.
Используйте DISTINCT, если вы просто хотите удалить дубликаты. Используйте GROUPY BY, если хотите применить агрегатные операторы (MAX, SUM, GROUP_CONCAT, ... или предложение HAVING).
Для отправленного вами запроса они идентичны. Но для других запросов это может не соответствовать действительности.
Например, это не то же самое, что:
SELECT C FROM myTbl GROUP BY C, D
Если вы используете DISTINCT с несколькими столбцами, набор результатов не будет сгруппирован, как с GROUP BY, и вы не сможете использовать агрегатные функции с DISTINCT.
В этом конкретном запросе нет никакой разницы. Но, конечно, если вы добавите какие-либо агрегированные столбцы, вам придется использовать group by.
group by используется в агрегатных операциях - например, когда вы хотите получить количество B с разбивкой по столбцу C
select C, count(B) from myTbl group by C
отчетливо звучит - вы получаете уникальные строки.
В sql server 2005 похоже, что оптимизатор запросов может оптимизировать разницу в упрощенных примерах, которые я запускал. Не знаю, можно ли на это рассчитывать во всех ситуациях.
Вы замечаете это только потому, что выбираете один столбец.
Попробуйте выбрать два поля и посмотрите, что произойдет.
Group By предназначена для использования следующим образом:
SELECT name, SUM(transaction) FROM myTbl GROUP BY name
Которая покажет сумму всех транзакций для каждого человека.
Это не вопрос агрегатов. В вашем примере SELECT c, d FROM mytbl GROUP BY C, D; фактически вернет тот же набор данных, что и SELECT DISTINCT C, D FROM mytbl; Это суть вопроса
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. Это даст вашей базе данных возможность оптимизировать запрос в соответствии с вашими потребностями.
Нет никакой разницы (по крайней мере, в SQL Server). Оба запроса используют один и тот же план выполнения.
http://sqlmag.com/database-performance-tuning/distinct-vs-group
Возможно, есть разница в является, если задействованы подзапросы:
Нет никакой разницы (в стиле Oracle):
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:32961403234212
Я полагаю, что есть вероятность незначительных различий в их исполнении. Я проверил планы выполнения для двух функционально эквивалентных запросов по этим строкам в 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 для этой цели. Это не просто привычка, это более четко указывает цель запроса.
Ответ MusiGenesis 'функционально правильный в отношении вашего вопроса, как указано; SQL Server достаточно умен, чтобы понять, что если вы используете «Группировать по» и не используете какие-либо агрегатные функции, то на самом деле вы имеете в виду «Отдельно» - и поэтому он генерирует план выполнения, как если бы вы просто использовали «Отдельно» . "
Тем не менее, я думаю, что важно также отметить ответ Хэнк - бесцеремонное обращение с «Group By» и «Distinct» может привести к некоторым пагубным ошибкам, если вы не будете осторожны. Не совсем правильно говорить, что это «не вопрос об агрегатах», потому что вы спрашиваете о функциональной разнице между двумя ключевыми словами SQL-запроса, одним из которых является предназначен для использования с агрегатами, а другим - нет.
Иногда молоток может вкрутить винт, но если у вас под рукой есть отвертка, зачем?
(для целей этой аналогии Hammer : Screwdriver :: GroupBy : Distinct и screw => get list of unique values in a table column)
Я полностью согласен с тобой, Скеолан. Я был очень удивлен, когда наткнулся на эту функциональность. Это не то, что я планирую использовать, а то, как все было сделано в этом новом месте, над которым я работаю.
По крайней мере, в Oracle 12 есть случаи, когда DISTINCT, получение различных значений с помощью UNION и GROUP BY работают по-разному. Сегодня у меня был случай, когда DISTINCT и отличное от UNION вызывают ошибку оракула, но GROUP BY работает; Я выбирал только 1 столбец из представления и не использовал агрегацию; Я до сих пор не понимаю, почему это потребовалось, но это подтверждает, что есть некоторая разница в исполнении. Как отмечают другие, он также позволяет вам GROUP BY столбцы не в select, хотя это редко бывает необходимо без агрегации.
Когда дело доходит до SQL, у вас всегда под рукой отвертка и молоток. Зачем забивать винт молотком?
Чтобы прояснить вашу аналогию - ваш молоток == GroupBy и отвертка == разные в данном случае?
Ух ты, у этого вопроса десятилетней давности все еще есть ноги! «Отличный» - это отвертка, если «список уникальных значений» - это винт. Я обновлю ответ, чтобы сделать аналогию более ясной.
В случае Amazon Redshift Spectrum лучше использовать GROUP BY, потому что он передается на уровень Spectrum, а Redshift отображает только данные результатов. Если DISTINCT используется для того же запроса к данным Spectrum, Spectrum перенесет все отсканированные данные в Redshift, а ведущий узел Redshift выполнит DISTINCT, поскольку это функция ведущего узла.
Пожалуйста, не используйте GROUP BY, когда вы имеете в виду DISTINCT, даже если они работают одинаково. Я предполагаю, что вы пытаетесь сэкономить миллисекунды на запросах, и я должен отметить, что время разработчика на порядки дороже, чем время компьютера.
Я всегда понимал, что использование отдельного - это то же самое, что группировка по каждому выбранному вами полю в том порядке, в котором вы их выбрали.
то есть:
select distinct a, b, c from table;
такой же как:
select a, b, c from table group by a, b, c
Согласовано, но будет ли это то же самое, что выбрать c, b, a из группы таблиц с помощью a, b, c
Да было бы то же самое
С точки зрения «SQL как язык» эти две конструкции эквивалентны, и какой из них вы выбираете, является одним из тех «стилей жизни», которые мы все должны сделать. Я думаю, что DISTINCT может быть более явным (и, следовательно, более внимательным к человеку, который унаследует ваш код и т. д.), Но это не означает, что конструкция GROUP BY является недопустимым выбором.
Я думаю, что «GROUP BY для агрегатов» - неправильный акцент. Люди должны знать, что заданная функция (MAX, MIN, COUNT и т. д.) Может быть опущена, чтобы они могли понять намерение кодировщика, когда это так.
Идеальный оптимизатор распознает эквивалентные конструкции SQL и всегда соответственно выберет идеальный план. Для вашего реального SQL-движка вы должны протестировать :)
PS обратите внимание, что позиция ключевого слова DISTINCT в предложении select может давать разные результаты, например. контраст:
SELECT COUNT(DISTINCT C) FROM myTbl;
SELECT DISTINCT COUNT(C) FROM myTbl;
Если вы используете GROUP BY без какой-либо агрегатной функции, то внутри она будет обрабатываться как DISTINCT, поэтому в этом случае нет разницы между GROUP BY и DISTINCT.
Но когда вам предоставляется предложение DISTINCT, лучше использовать его для поиска ваших уникальных записей, потому что цель GROUP BY - добиться агрегирования.
Я прочитал все вышеперечисленные комментарии, но не видел, чтобы кто-нибудь указал на основное различие между 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 строк.
Причина в том, что я сказал выше, чтобы они могли вести себя по-другому!
Это потому, что, хотя вы группируете только по Name во втором запросе, ключевое слово distinct применяется как к столбцам Name, так и к вашему столбцу ROW_NUMBER() в предложении select первого запроса. Если бы вы также сгруппировали по первому столбцу во втором запросе, запросы вернули бы те же результаты.
Это результат order of execution предложений SQL, который (в общем смысле) FROM and ON (joins), WHERE, GROUP BY, HAVING, SELECT, DISTINCT, ORDER BY, LIMIT / OFFSET / TOP, поэтому во втором запросе имена сокращаются по группам, а затем на row_number () применяется, в результате чего получается одна строка для каждого уникального имени. В первом запросе row_number () применяется до применения отдельного, и из-за характера функции row_number () каждая строка получает уникальное целое число, поэтому каждая строка возвращается, даже если есть повторяющиеся значения имени.
Нет существенной разницы между предложением group by и отличным, за исключением использования агрегатных функций. Оба могут использоваться для различения значений, но если с точки зрения производительности лучше использовать группу по. Когда используется особое ключевое слово, внутри используется операция сортировки, которую можно просмотреть в плане выполнения.
Попробуйте простой пример
Объявить таблицу @tmpresult ( Id tinyint )
Вставить в @tmpresult Выберите 5 Союз всех Выберите 2 Союз всех Выберите 3 Союз всех Выберите 4
Выберите отличное Идентификатор От @tmpresult
отличные и групповые по обоим
Я знаю, что это старый пост. Но бывает, что у меня был запрос, который использовал group by просто для возврата отдельных значений при использовании этого запроса в отчетах жабы и оракула, все работало нормально, я имею в виду хорошее время ответа. Когда мы перешли с Oracle 9i на 11g, время отклика в Toad было отличным, но в отчете потребовалось около 35 минут, чтобы закончить отчет, тогда как при использовании предыдущей версии это заняло около 5 минут.
Решением было изменить группу и использовать DISTINCT, и теперь отчет запускается примерно за 30 секунд.
Надеюсь, это будет полезно для кого-то с такой же ситуацией.
Помимо того факта, что в отличие от DISTINCT, GROUP BY позволяет агрегировать данные на группу (о чем упоминалось во многих других ответах), наиболее важным различием, на мой взгляд, является тот факт, что две операции «происходят» на двух очень разных шагах в логический порядок операций, выполняемых в операторе SELECT .
Вот самые важные операции:
FROM (включая JOIN, APPLY и т. д.)WHEREGROUP BY(можно удалить дубликаты)HAVINGSELECTDISTINCT(можно удалить дубликаты)UNION, INTERSECT, EXCEPT(можно удалить дубликаты)ORDER BYOFFSETLIMITКак видите, логический порядок каждой операции влияет на то, что с ней можно делать, и как он влияет на последующие операции. В частности, тот факт, что операция GROUP BY"случается раньше" операция SELECT (проекция) означает, что:
Пример, в котором не зависит от проекции, полезен, если вы хотите вычислить оконные функции для различных значений:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
GROUP BY rating
При запуске против База данных Сакила это дает:
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
Одним из недостатков 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
Я написал об этой теме более подробно в блоге
Я был искренне удивлен, увидев, что по этому вопросу сразу не обсуждался порядок казни. Спасибо, тоже очень красиво объяснено. По вашему пункту 2. некоторые (один?) БД позволяют использовать псевдонимы выбора во всем запросе (я знаю, что это Teradata, но это исключение).
@Used_By_Already: Конечно, некоторые базы данных это делают. Многие базы данных позволяют использовать эти псевдонимы только частично (например, не WHERE, но, возможно, GROUP BY). В любом случае, я думаю, что это плохая идея, и я предлагаю никогда не использовать эту функцию по причинам переносимости и обслуживания. "Вдруг" больше не получится, например при наложении псевдонима на агрегатную функцию или оконную функцию.
never using that feature for portability and maintenance reasons !! согласен на 100% ... И теперь я тоже просматриваю ваш блог, отличная работа. Ваше здоровье.
Функциональная эффективность совершенно другая. Если вы хотите выбрать только «возвращаемое значение», кроме повторяющегося, лучше использовать отдельное значение, чем группировать по. Поскольку "группировать по" включать (сортировка + удаление), "отдельные" включать (удалять)
С точки зрения набора результатов не имеет значения, используете ли вы DISTINCT или GROUP BY в Teradata. Набор ответов будет таким же.
С точки зрения производительности это не одно и то же.
Чтобы понять, что влияет на производительность, вам нужно знать, что происходит в Teradata при выполнении оператора с DISTINCT или GROUP BY.
В случае DISTINCT строки перераспределяются немедленно без какой-либо предварительной агрегации, в то время как в случае GROUP BY на первом этапе выполняется предварительная агрегация, и только затем уникальные значения перераспределяются между AMP.
Не думайте, что GROUP BY всегда лучше с точки зрения производительности. Когда у вас много разных значений, этап предварительной агрегации GROUP BY не очень эффективен. Teradata должна отсортировать данные, чтобы удалить дубликаты. В этом случае может быть лучше сначала выполнить повторное распространение, то есть использовать оператор DISTINCT. Только при наличии большого количества повторяющихся значений оператор GROUP BY, вероятно, является лучшим выбором, поскольку выполняется только один раз, когда выполняется шаг дедупликации, после перераспределения.
Короче говоря, DISTINCT vs. GROUP BY в Teradata означает:
GROUP BY -> для множества дубликатов DISTINCT -> нет или только несколько дубликатов. Иногда при использовании DISTINCT у вас не хватает места для буферизации на AMP. Причина в том, что перераспределение происходит немедленно, и перекос может привести к нехватке места для AMP.
Если это произойдет, у вас, вероятно, больше шансов с GROUP BY, поскольку дубликаты уже удалены на первом этапе, и меньше данных перемещается через AMP.
Что такое Teradata?
Teradata - это система управления реляционными базами данных (RDBMS), способная поддерживать множество одновременных пользователей с различных клиентских платформ. Teradata совместима со стандартом ANSI и полностью построена на параллельной архитектуре.
В Hive (HQL) GROUP BY может быть намного быстрее, чем DISTINCT, потому что первый не требует сравнения всех полей в таблице.
См .: https://sqlperformance.com/2017/01/t-sql-queries/surprises-assumings-group-by-distinct.
Иногда они могут дать вам одинаковые результаты, но они предназначены для использования в другом смысле / случае. Основное отличие заключается в синтаксисе.
Обратите внимание на пример ниже. 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
Обычно мы можем использовать DISTINCT для устранения дубликатов в определенном столбце в таблице.
In Case of 'GROUP BY' we can Apply the Aggregation Functions like
AVG,MAX,MIN,SUM, andCOUNTon Specific column and fetch the column name and it aggregation function result on the same column.
Пример :
select specialColumn,sum(specialColumn) from yourTableName group by specialColumn;
С точки зрения использования GROUP BY используется для группировки тех строк, которые вы хотите вычислить. DISTINCT не производит никаких вычислений. Он не покажет повторяющихся строк.
Я всегда использовал DISTINCT, если хочу представить данные без дубликатов.
Если я хочу произвести расчеты, например, суммировать общее количество манго, я буду использовать GROUP BY.
Это не вопрос об агрегатах, это GROUP BY, функционирующая так же, как и отдельная, когда агрегатная функция отсутствует.