从仅重复删除功能的角度来看有什么区别
除了不同的是DISTINCT
,GROUP BY
允许在每个组中汇总数据(许多其他答案都提到过)这一事实,我认为最重要的区别是,这两个操作以逻辑顺序SELECT
在两个非常不同的步骤“发生” 语句中执行的操作的一部分。
这是最重要的操作:
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数据库上运行时,将产生:
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
我已经在博客文章中更深入地讨论了这个主题