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

SELECT c FROM myTbl GROUP BY C

与以下结果相同:

SELECT DISTINCT C FROM myTbl

我很好奇,SQL 引擎处理命令的方式有什么不同,或者它们真的是同一件事吗?

我个人更喜欢独特的语法,但我确信这更多的是出于习惯。

编辑:这不是一个关于聚合的问题。指某东西的用途 GROUP BY 可以理解为聚合函数。

有帮助吗?

解决方案

MusiGenesis '的回复是功能上的关于你所陈述的问题的正确答案; SQL Server足够智能,可以实现如果你使用“分组依据”,并且没有使用任何聚合函数,那么你实际意味着什么是“Distinct” - 因此它会生成执行计划,就像您只是使用“Distinct。”

一样

但是,我认为重要的是要注意汉克的反应 - 对“Group By”的骑士对待和“区别”如果你不小心,可能会导致一些有害的陷阱。说这不是关于聚合的问题并不完全正确。因为您询问两个SQL查询关键字之间的功能差异,其中一个意味着与聚合一起使用,而其中一个不是。

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

(出于类比的目的, Hammer:Screwdriver :: GroupBy:Distinct screw =>获取表格列中的唯一值列表

其他提示

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

例如,如果您有一堆购买记录,并且您想知道每个部门花了多少钱,那么您可以执行以下操作:

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

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

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

从单纯的重复删除功能的角度来看有什么区别

除了与事实不同之外 DISTINCT, GROUP BY 允许聚合数据 每组 (许多其他答案已经提到过),我认为最重要的区别是这两个操作“发生”在两个非常不同的步骤中 在a中执行的操作的逻辑顺序 SELECT 陈述.

以下是最重要的操作:

  • FROM (包括 JOIN, APPLY, , ETC。)
  • WHERE
  • GROUP BY (可以删除重复项)
  • 聚合
  • HAVING
  • 窗口函数
  • SELECT
  • DISTINCT (可以删除重复项)
  • UNION, INTERSECT, EXCEPT (可以删除重复项)
  • 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

当对抗 萨基拉数据库, ,这会产生:

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

这是有效的(重复表达式)

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

我在博客文章中更深入地讨论了这个主题

我预计他们的执行可能存在微妙的差异。 我在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之间的主要区别。

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行。

原因就在于我上面所说的,所以他们可以表现得不同!

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

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

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。这将使您的数据库有机会根据您的需求优化查询。

当你的意思是DISTINCT时,请不要使用GROUP BY,即使它们恰好相同。我假设你试图从查询中减少毫秒数,我必须指出开发人员的时间比计算机时间贵一个数量级。

如果您使用的GROUP BY没有任何聚合函数,那么在内部它将被视为DISTINCT,因此在这种情况下,GROUP BY和DISTINCT之间没有区别。

但是当你被提供DISTINCT子句时,最好使用它来查找你的唯一记录,因为GROUP BY的目标是实现聚合。

group by用于聚合操作 - 比如当你想得到按C列分解的B数时

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

与众不同之处在于它 - 您获得了独特的行。

在sql server 2005中,看起来查询优化器能够优化我运行的简单示例中的差异。不过,如果你能在所有情况下都依赖它,那就不知道了。

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

从“SQL语言”的角度来看,这两个结构是等价的,你选择的是我们都必须做出的“生活方式”选择之一。我认为有一个很好的例子,DISTINCT更明确(因此对于将继承你的代码的人更加体贴)但这并不意味着GROUP BY结构是无效的选择。

我认为'GROUP BY是聚合'是错误的重点。 Folk应该知道可以省略set函数(MAX,MIN,COUNT等),这样他们就可以理解编码器的意图。

理想的优化器将识别等效的SQL构造,并始终相应地选择理想的计划。对于您现实生活中的SQL引擎,您必须测试:)

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

SELECT COUNT(DISTINCT C) FROM myTbl;

SELECT DISTINCT COUNT(C) FROM myTbl;

在Teradata透视图中

从结果集的角度来看,如果在Teradata中使用DISTINCT或GROUP BY并不重要。答案集将是相同的。

从性能的角度来看,它不一样。

要了解影响性能的因素,您需要了解在使用DISTINCT或GROUP BY执行语句时Teradata上会发生什么。

在DISTINCT的情况下,行立即重新分配而不进行任何预聚合,而在GROUP BY的情况下,在第一步中进行预聚合,然后才在AMP中重新分配唯一值。

现在不要认为从性能的角度来看GROUP BY总是更好。当您有许多不同的值时,GROUP BY的预聚合步骤效率不高。 Teradata必须对数据进行排序以删除重复项。在这种情况下,首先重新分配可能更好,即使用DISTINCT语句。仅当存在许多重复值时,GROUP BY语句可能是更好的选择,因为只有在重新分发后才执行重复数据删除步骤。

简而言之,Teradata中的DISTINCT与GROUP BY意味着:

GROUP BY - >对于许多重复 DISTINCT - >没有或只有一些重复。 有时,使用DISTINCT时,AMP上的假脱机空间不足。原因是重新分配立即发生,并且倾斜可能导致AMP耗尽空间。

如果发生这种情况,您可能更有可能使用GROUP BY,因为重复项已在第一步中删除,并且较少的数据会在AMP之间移动。

您只是注意到这一点,因为您选择了一个列。

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

Group By旨在像这样使用:

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

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

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

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

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

我总是理解它的方式是使用distinct与按选择顺序选择的每个字段进行分组相同。

即:

select distinct a, b, c from table;

与:

相同
select a, b, c from table group by a, b, c
功能效率完全不同。 如果您只想选择“返回值”,除了重复一个,使用distinct比group by更好。因为“分组依据”包括(排序+删除),“不同”包括(删除)

在Hive(HQL)中,group by可以比distinct更快,因为前者不需要比较表中的所有字段。请参阅 https://sqlperformance.com/2017 / 01 / T-SQL查询/意外-假设组逐不同

除了使用聚合函数之外,group by和distinct子句之间没有显着差异。 两者都可用于区分值,但如果在性能上观点,则group by更好。 当使用distinct关键字时,它在内部使用可以在执行计划中查看的排序操作。

尝试简单的例子

声明@tmpresult表 (   Id tinyint )

插入@tmpresult 选择5 全联盟 选择2 全联盟 选择3 全联盟 选择4

选择不同 ID 来自@tmpresult

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top