GROUP BY和DISTINCT是否有区别?

有一天我学到了关于SQL的一些简单的东西:

SELECT c FROM myTbl GROUP BY C 

具有与以下相同的结果:

 SELECT DISTINCT C FROM myTble 

我感到好奇的是,SQL引擎处理命令的方式有什么不同,还是真的是一回事?

我个人比较喜欢独特的语法,但我相信它比其他任何事都更习惯于习惯。

编辑:这不是一个关于聚合的问题。 了解使用GROUP BY与聚合函数。

MusiGenesis的回答在function上是正确的,就你所说的问题而言; SQL Server足够聪明地认识到,如果你使用“Group By”而不使用任何聚合函数,那么你实际上的意思是“Distinct” – 因此它产生一个执行计划,就好像你只是使用“Distinct “。

不过,我认为重要的是要注意到汉克的反应 – 如果你不小心的话,“集体”和“不同”的骑士待遇可能会导致一些有害的瑕疵。 说这不是一个关于聚集的问题是不完全正确的,因为你在问两个SQL查询关键字之间的function差别,其中一个是用于聚合 ,另一个则不是。

有时锤子可以用螺丝刀驱动,但是如果你有方便的螺丝刀,为什么呢?

GROUP BY允许您使用聚合函数,如AVGMAXMINSUMCOUNT 。 另一方面DISTINCT只是删除重复。

例如,如果您有一堆购买logging,并且想要知道每个部门花了多less钱,则可以执行以下操作:

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

这将为每个部门提供一行,包含部门名称以及该部门所有行中所有amount值的总和。

没有区别 (在SQL Server中,至less)。 这两个查询使用相同的执行计划。

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

如果您只想删除重复项,请使用DISTINCT 。 如果要应用聚合运算符( MAXSUMGROUP_CONCAT ,…或HAVING子句),请使用GROUPY BY

我期望在执行过程中有细微差别的可能性。 我检查了Oracle 10g中这两行function相同的查询的执行计划:

 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”,但估算的成本等是一致的。 然后我执行这些跟踪和两个实际操作计数是相同的(除了第二个由于caching不必做任何物理读取)。

但是我认为,因为操作名称是不同的,所以执行会遵循一些不同的代码path,从而打开更大的差异的可能性。

我认为你应该更喜欢这种用途的DISTINCT语法。 这不仅仅是习惯,更清楚地表明查询的目的。

对于您发布的查询,它们是相同的。 但对于其他查询,可能并非如此。

例如,它不是一样的:

 SELECT C FROM myTbl GROUP BY C, D 

如果对多列使用DISTINCT,那么结果集将不会像GROUP BY那样分组,您不能将集合函数与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个名称,其中1个是另一个的副本,则第一个查询返回10行,而第二个查询返回9行。

原因是我上面所说的,所以他们可以有不同的performance!

与单纯的重复删除function的观点有什么不同?

除了与DISTINCT不同的是, GROUP BY允许汇总每个组的数据(这已经被许多其他答案提及),我认为最重要的差异是这两个操作“发生”在两个非常不同的步骤在SELECT语句中执行的操作的逻辑顺序 。

这是最重要的操作:

  • FROM (包括JOINAPPLY等)
  • WHERE
  • GROUP BY (可以删除重复项)
  • 聚合
  • HAVING
  • 窗口function
  • SELECT
  • DISTINCT (可以删除重复项)
  • UNIONINTERSECTEXCEPT (可以删除重复项)
  • 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 

这是有效的(重复expression式)

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

这也是有效的(嵌套expression式)

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

我在博客文章中更深入地写了这个话题

GROUP BY具有与DISTINCT函数不同(heh)的非常具体的含义。

GROUP BY使查询结果使用选定的expression式进行分组,然后可以应用聚合函数,这些函数将作用于每个组,而不是整个结果集。

以下是一个可能有所帮助的例子:

给定一个如下所示的表格:

 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没有区别。

但是,当您提供DISTINCT子句时更好地使用它来查找唯一的logging,因为GROUP BY的目标是实现聚合。

group by用于合计操作 – 就像当你想获得按列C细分的Bs数一样

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

不同的是它听起来像 – 你得到独特的行。

在sql server 2005中,它看起来像查询优化器能够优化我运行的简单例子中的差异。 不知道,如果你能在所有的情况下,依靠这一点,但。

当你的意思是DISTINCT时,请不要使用GROUP BY,即使它们碰巧是一样的。 我假设你正试图从查询中减less毫秒数,而且我必须指出,开发者的时间比计算机时间要贵得多。

在那个特定的查询中没有区别。 但是,当然,如果你添加任何聚合列,那么你将不得不使用group by。

从“SQL语言”的angular度来看,这两个结构是等价的,你select哪一个是我们必须做的那些“生活方式”select之一。 我认为DISTINCT是一个很好的例子,因为它更加明确(因此对于inheritance你的代码的人会更加考虑),但这并不意味着GROUP BY构造是无效的select。

我认为这个“GROUP BY是为了聚合”是错误的重点。 民间应该知道,设置函数(MAX,MIN,COUNT等)可以省略,这样他们就可以了解编码器的意图了。

理想的优化器将识别等效的SQL结构,并且总会相应地select理想的计划。 对于您select的真实生活SQL引擎,您必须testing:)

PS注意DISTINCT关键字在select子句中的位置可能会产生不同的结果,例如对比度:

 SELECT COUNT(DISTINCT C) FROM myTbl; SELECT DISTINCT COUNT(C) FROM myTbl; 

你只注意到,因为你正在select一个列。

尝试select两个字段,看看会发生什么。

Group By是为了像这样使用:

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

这将显示每个人的所有交易的总和。

我知道这是一个旧的职位。 但是,碰巧有一个查询使用组,只是在蟾蜍中使用该查询时返回不同的值,而oracle报告一切正常,我的意思是一个很好的响应时间。 当我们从Oracle 9i迁移到11g时,蟾蜍的响应时间非常好,但是在报告中花了约35分钟完成报告,使用以前的版本花了大约5分钟。

解决方法是改变组,并使用DISTINCT,现在报告运行约30秒。

我希望这对于有相同情况的人有用。

我一直理解的方式是,使用不同的分组是按照您select的顺序select的每个字段进行分组。

即:

 select distinct a, b, c from table; 

是相同的:

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

我以前有这个问题,我需要从我的400万行表中追加三列(三列到新表的一个新列),但只有不同的列。

所以我用“group by”方法运行了包含这个查询的存储过程,花了32分钟。 然后我又跑了一遍,但用“明显”的方法,花了25分钟。

这是相同的结果,但用第二种方法要快一点

除了聚合函数的使用之外,group by和distinct clause之间没有显着的区别。 两者都可以用来区分价值,但是如果在性能上来看group by是更好的。 当使用distinct关键字时,内部使用可以在执行计划中查看的sorting操作。

试试简单的例子

声明@tmpresult表(Id tinyint)

插入@tmpresultselect5 Union allselect2 Union allselect3 Union allselect4

从@tmpresult中select不同的ID