GROUP BY和DISTINCT有什么区别
前几天,我学到了一些关于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;