GROUP BY和DISTINCT有什么区别

时间:2020-03-06 15:02:50  来源:igfitidea点击:

前几天,我学到了一些关于SQL的简单知识:

SELECT c FROM myTbl GROUP BY C

与以下结果相同:

SELECT DISTINCT C FROM myTbl

我很好奇,SQL引擎处理命令的方式是否有所不同,或者它们确实是同一回事?

我个人更喜欢独特的语法,但是我确信它比其他任何东西都更习惯。

编辑:这不是关于聚合的问题。可以理解将" GROUP BY"与聚合函数一起使用。

解决方案

它们具有不同的语义,即使它们在特定数据上碰巧得到相同的结果。

使用GROUP BY可以使用聚合函数,例如AVG,MAX,MIN,SUM和COUNT。
另一方面,DISTINCT只是删除重复项。

例如,如果我们有一堆采购记录,并且想知道每个部门花费了多少,则可以执行以下操作:

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

这将为我们提供每个部门一行,其中包含部门名称以及该部门所有行中所有"金额"值的总和。

如果我们只想删除重复项,请使用DISTINCT。如果要应用聚合运算符(" MAX"," SUM"," GROUP_CONCAT",...或者" HAVING"子句),请使用" GROUPY BY"。

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

例如,它与以下内容不同:

SELECT C FROM myTbl GROUP BY C, D

如果将DISTINCT与多列一起使用,则结果集将不会像GROUP BY那样被分组,并且DISTINCT不能使用聚合函数。

在该特定查询中没有区别。但是,当然,如果添加任何聚合列,则必须使用group by。

group by用于汇总操作-例如,当我们想获得按列C细分的B计数时

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

听起来像是与众不同-我们获得了唯一的行。

在sql server 2005中,查询优化器看起来能够优化我运行的简单示例中的差异。但是,如果我们可以在所有情况下都依靠它,Dunno。

我们仅注意到这一点,因为我们选择的是单列。

尝试选择两个字段,然后看看会发生什么。

按以下方式使用分组依据:

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

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

GROUP BY具有非常特殊的含义,与DISTINCT函数截然不同(heh)。

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

如果涉及子查询,则可能有所不同:

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

我希望它们在执行上可能会有细微的差异。
我沿着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 |
---------------------------------------------------------------------------

中间操作略有不同:"哈希组"与"哈希唯一",但估计成本等相同。然后,我在跟踪时执行了这些操作,并且两者的实际操作计数相同(除了第二个操作由于缓存而不必进行任何物理读取)。

但是我认为,由于操作名称不同,执行将遵循一些不同的代码路径,这带来了更大差异的可能性。

我认为我们应该为此使用DISTINCT语法。这不仅是习惯,它还更清楚地表明了查询的目的。

就我们提出的问题而言,MusiGenesis的回答在功能上是正确的; SQL Server足够聪明,可以意识到如果我们使用的是"分组依据"而不使用任何聚合函数,那么我们实际上的意思是"不同的",因此它生成的执行计划就像我们只是使用"不同的"一样。 "

但是,我认为重要的是要注意到Hank的回应以及对" Group By"和" Distinct"的轻率对待,如果我们不注意的话,可能会导致一些危险的陷阱。说这不是"关于聚合的问题"并不完全正确,因为我们要问的是两个SQL查询关键字之间的功能差异,其中一个是与聚合一起使用的,而另一个则不是。

锤子有时可以用螺丝打入,但是如果我们有一把螺丝刀,为什么要打扰呢?

(...出于这个类比的目的,汉默(Hammer):螺丝刀::: GroupBy:GroupBy:Distinct和`screw =>获取表列中唯一值的列表)

即使意思是DISTINCT,也请不要使用GROUP BY,即使它们碰巧也一样。我假设我们正在尝试从查询中节省毫秒,并且我必须指出,开发人员的时间比计算机的时间要贵几个数量级。

我一直了解的方式是,使用distinct等同于按照选择顺序对每个选定字段进行分组。

IE:

select distinct a, b, c from table;

是相同的:

select a, b, c from table group by 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;