前几天我学了一些关于SQL的简单知识:
SELECT c FROM myTbl GROUP BY C
结果与:
SELECT DISTINCT C FROM myTbl
我好奇的是,SQL引擎处理命令的方式有什么不同,还是它们真的是一样的东西?
我个人更喜欢独特的语法,但我相信这更多是出于习惯而不是其他原因。
编辑:这不是一个关于聚合的问题。理解了GROUP BY与聚合函数的使用。
前几天我学了一些关于SQL的简单知识:
SELECT c FROM myTbl GROUP BY C
结果与:
SELECT DISTINCT C FROM myTbl
我好奇的是,SQL引擎处理命令的方式有什么不同,还是它们真的是一样的东西?
我个人更喜欢独特的语法,但我相信这更多是出于习惯而不是其他原因。
编辑:这不是一个关于聚合的问题。理解了GROUP BY与聚合函数的使用。
当前回答
我预计在执行上可能会有细微的差异。 我检查了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唯一”,但估计成本等是相同的。然后,我在跟踪的情况下执行这些操作,两者的实际操作计数是相同的(除了第二个操作由于缓存而不需要进行任何物理读取)。
但我认为,由于操作名称不同,执行将遵循不同的代码路径,这可能会带来更大的差异。
出于这个目的,我认为您应该更喜欢DISTINCT语法。这不仅仅是习惯,它更清楚地表明了查询的目的。
其他回答
在使用方面,GROUP BY用于对要计算的行进行分组。DISTINCT将不做任何计算。它不会显示重复的行。
如果我想要呈现无重复的数据,我总是使用DISTINCT。
如果我想做计算,比如合计芒果的总数,我会使用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;
我预计在执行上可能会有细微的差异。 我检查了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唯一”,但估计成本等是相同的。然后,我在跟踪的情况下执行这些操作,两者的实际操作计数是相同的(除了第二个操作由于缓存而不需要进行任何物理读取)。
但我认为,由于操作名称不同,执行将遵循不同的代码路径,这可能会带来更大的差异。
出于这个目的,我认为您应该更喜欢DISTINCT语法。这不仅仅是习惯,它更清楚地表明了查询的目的。
我阅读了上面所有的评论,但除了聚合位之外,没有看到任何人指出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行。
原因就是我上面说的,这样他们就能表现得不一样!
对于你发布的查询,它们是相同的。但对于其他查询,这可能不是真的。
例如,它不等同于:
SELECT C FROM myTbl GROUP BY C, D