从单纯的重复删除功能的角度来看有什么区别
除了与DISTINCT 不同,GROUP BY 允许聚合数据每组(许多其他答案已经提到),我认为最重要的区别是事实这两个操作“发生”在logical order of operations that are executed in a SELECT statement 中的两个非常不同的步骤。
以下是最重要的操作:
-
FROM(包括JOIN、APPLY等)
WHERE
-
GROUP BY (可以删除重复项)
- 聚合
HAVING
- 窗口函数
SELECT
-
DISTINCT (可以删除重复项)
-
UNION, INTERSECT, EXCEPT (可以删除重复项)
ORDER BY
OFFSET
LIMIT
如您所见,每个操作的逻辑顺序会影响可以用它做什么以及它如何影响后续操作。特别是,GROUP BY 操作“发生在”SELECT 操作(投影)这一事实意味着:
- 它不依赖于投影(这可能是一个优势)
- 它不能使用投影中的任何值(这可能是一个缺点)
1。它不依赖于投影
一个不依赖于投影的例子是有用的,如果你想计算不同值的窗口函数:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
GROUP BY rating
当针对Sakila database 运行时,会产生:
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
旁注:In this particular case, we could also use 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
I've written about this topic more in depth in a blog post