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

SELECT c FROM myTbl GROUP BY C

结果与:

SELECT DISTINCT C FROM myTbl

我好奇的是,SQL引擎处理命令的方式有什么不同,还是它们真的是一样的东西?

我个人更喜欢独特的语法,但我相信这更多是出于习惯而不是其他原因。

编辑:这不是一个关于聚合的问题。理解了GROUP BY与聚合函数的使用。


当前回答

如果对多个列使用DISTINCT,结果集将不会像使用GROUP BY那样进行分组,并且不能对DISTINCT使用聚合函数。

其他回答

对于你发布的查询,它们是相同的。但对于其他查询,这可能不是真的。

例如,它不等同于:

SELECT C FROM myTbl GROUP BY C, D

你之所以注意到这一点,是因为你只选择了一列。

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

Group By的用法如下:

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

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

在Teradata透视图:

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

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

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

在DISTINCT的情况下,行被立即重新分配,而不发生任何预聚合,而在GROUP BY的情况下,第一步完成预聚合,然后才在amp之间重新分配唯一值。

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

简而言之,DISTINCT vs. GROUP BY在Teradata中的意思是:

GROUP BY ->用于多个重复 DISTINCT ->没有或只有几个重复项。 在使用DISTINCT时,有时会耗尽AMP上的线轴空间。原因是重新分配立即发生,倾斜可能会导致AMP耗尽空间。

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

仅仅从重复删除功能的角度来看有什么不同

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

以下是最重要的操作:

FROM(包括JOIN、APPLY等) 在哪里 GROUP BY(可以删除重复项) 聚合 有 窗口函数 选择 DISTINCT(可以删除重复项) UNION, INTERSECT, EXCEPT(可删除重复项) 命令 抵消 限制

如您所见,每个操作的逻辑顺序影响着可以用它做什么以及它如何影响后续操作。特别地,GROUP BY操作“发生在”SELECT操作(投影)之前的事实意味着:

它不依赖于投影(这可能是一个优势) 它不能使用来自投影的任何值(这可能是一个缺点)

1. 它不依赖于投影

一个不依赖于投影的例子是,如果你想计算不同值的窗口函数:

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

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报告一切都工作得很好,我的意思是一个很好的响应时间。当我们从Oracle 9i迁移到11g时,Toad中的响应时间非常好,但在报告中,完成报告需要35分钟,而使用以前的版本大约需要5分钟。

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

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