前几天我学到了一些关于SQL的简单知识:
SELECT c FROM myTbl GROUP BY C
结果与:
SELECT DISTINCT C FROM myTbl
我很好奇,SQL引擎处理命令的方式有什么不同,还是它们真的是同一个东西?
我个人更喜欢不同的语法,但我相信它更多地出于习惯而不是其他任何东西.
编辑:这不是关于聚合的问题.的使用GROUP BY
与聚合函数了解.
就所陈述的问题而言,MusiGenesis的回答在功能上是正确的; SQL Server足够智能,可以意识到如果你使用"分组依据"并且不使用任何聚合函数,那么你实际意味着什么是"区别" - 因此它会生成一个执行计划,就像你只是简单地使用"Distinct"一样".
然而,我认为重要的是要注意汉克的回应 - 如果你不小心的话,对"Group By"和"Distinct"的骑士待遇可能导致一些有害的陷阱.说这不是关于聚合的问题并不完全正确,因为你问的是两个SQL查询关键字之间的功能差异,其中一个用于聚合,而其中一个不是.
有时锤子可以用螺丝钉驱动,但如果你有方便的螺丝刀,为什么要费心呢?
(出于这个类比的目的,Hammer : Screwdriver :: GroupBy : Distinct
和screw => get list of unique values in a table column
)
GROUP BY
让您使用聚合函数,如AVG
,MAX
,MIN
,SUM
,和COUNT
.另一只手DISTINCT
只是删除重复.
例如,如果您有一堆购买记录,并且您想知道每个部门花了多少钱,您可能会执行以下操作:
SELECT department, SUM(amount) FROM purchases GROUP BY department
这将为每个部门提供一行,包含部门名称以及该部门amount
所有行中所有值的总和.
没有区别(至少在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
除了不同的事实DISTINCT
,GROUP BY
允许每组聚合数据(许多其他答案已经提到),我认为最重要的差异是这两个操作在逻辑顺序的SELECT
两个非常不同的步骤"发生"的事实在语句中执行的操作.
以下是最重要的操作:
FROM
(包括JOIN
,APPLY
等)
WHERE
GROUP BY
(可以删除重复)
聚合
HAVING
窗口功能
SELECT
DISTINCT
(可以删除重复)
UNION
,INTERSECT
,EXCEPT
(可删除重复)
ORDER BY
OFFSET
LIMIT
正如您所看到的,每个操作的逻辑顺序会影响可以执行的操作以及它如何影响后续操作.特别是,该事实GROUP BY
操作"之前发生"的SELECT
操作(投影)表示:
它不依赖于投影(这可能是一个优势)
它不能使用投影中的任何值(这可能是一个缺点)
不依赖于投影的示例很有用,如果要在不同的值上计算窗口函数:
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
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
我在博文中更深入地介绍了这个主题
使用DISTINCT
,如果你只是想删除重复.使用GROUPY BY
,如果你想将集合运算符(MAX
,SUM
,GROUP_CONCAT
,...,或HAVING
条款).
我预计他们的执行可能存在微妙的差异.我在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语法.这不仅仅是习惯,它更清楚地表明了查询的目的.
对于您发布的查询,它们是相同的.但对于其他可能不正确的查询.
例如,它与以下内容不同:
SELECT C FROM myTbl GROUP BY C, D
我阅读了上述所有评论,但没有看到任何人指出除了聚合位之外Group By和Distinct之间的主要区别.
因为他们是由算法逐个读取不同返回所有的行,然后去复制他们,而集团通过去重复数据删除的行.
这意味着他们可以产生不同的结果!
例如,以下代码会生成不同的结果:
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行.
原因就是我上面所说的,所以他们可以表现得不同!
如果对多列使用DISTINCT,则不会将结果集按GROUP BY分组,也不能将聚合函数与DISTINCT一起使用.
它们具有不同的语义,即使它们碰巧在您的特定数据上具有相同的结果.
当你的意思是DISTINCT时,请不要使用GROUP BY,即使它们恰好相同.我假设你正试图从查询中减少毫秒数,我必须指出开发人员的时间比计算机时间贵几个数量级.
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.这将使您的数据库有机会根据您的需求优化查询.
如果您在没有任何聚合函数的情况下使用GROUP BY,那么在内部它将被视为DISTINCT,因此在这种情况下,GROUP BY和DISTINCT之间没有区别.
但是,如果为您提供DISTINCT子句更好地使用它来查找您的唯一记录,因为GROUP BY的目标是实现聚合.