操作的句法与逻辑顺序
我认为,只有了解了logical order of operations in SQL,才能真正了解relationship between DISTINCT and ORDER BY(或GROUP BY,就此而言)的困惑。它不同于操作的句法顺序,后者是混淆的主要来源。
在这个例子中,考虑到它的句法接近性,它看起来好像DISTINCT与SELECT相关,但它实际上是一个在之后应用的运算符@ 987654335@(投影)。由于DISTINCT 的性质(删除重复行),在DISTINCT 操作(包括ORDER BY 子句)之后 行的所有未投影内容不再可用.根据logical order of operations (simplified):
-
FROM(产生所有可能的列引用)
-
WHERE(可以使用来自FROM的所有列引用)
-
SELECT(可以使用来自FROM的所有列引用,并创建新的表达式,并为它们取别名)
-
DISTINCT(对SELECT投影的元组进行操作)
-
ORDER BY(取决于DISTINCT的存在,可以对SELECT投影的元组进行操作,如果DISTINCT不存在*也许(取决于方言)也可以在其他表达式上)
DISTINCT 和 ORDER BY 呢?
事实上,没有DISTINCT,ORDER BY 也可以访问(在某些方言中)没有被预测的东西可能有点奇怪,当然有用。例如。这行得通:
WITH emp (id, fname, name) AS (
VALUES (1, 'A', 'A'),
(2, 'C', 'A'),
(3, 'B', 'B')
)
SELECT id
FROM emp
ORDER BY fname DESC
dbfiddle here。制作
id
--
2
3
1
当您添加 DISTINCT 时,这会发生变化。这不再有效:
WITH emp (id, fname, name) AS (
VALUES (1, 'A', 'A'),
(2, 'C', 'A'),
(3, 'B', 'B')
)
SELECT DISTINCT name
FROM emp
ORDER BY fname DESC
dbfiddle here。错误是:
错误:对于 SELECT DISTINCT,ORDER BY 表达式必须出现在选择列表中
第 8 行:按 fname DESC 排序
因为fname 的值是什么,您会将name = A 赋予什么? A 还是 C?答案将决定您是得到A、B 还是B、A。无法决定。
PostgreSQL DISTINCT ON
现在,正如above linked article 中所述,PostgreSQL 支持对此的例外情况,这有时会很有用:DISTINCT ON(另见questions like these):
WITH emp (id, fname, name) AS (
VALUES (1, 'A', 'A'),
(2, 'C', 'A'),
(3, 'B', 'B')
)
SELECT DISTINCT ON (name) id, fname, name
FROM emp
ORDER BY name, fname, id
dbfiddle here,制作:
id |fname|name
---|-----|----
1 |A |A
3 |B |B
此查询只允许生成 name 的不同值,然后对于每个重复的行,取第一个给定 ORDER BY 子句的值,这使得每个不同组的选择明确。 This can be emulated in other RDBMS using window functions.