操作的句法与逻辑顺序
我认为只有理解了 SQL 中操作的逻辑顺序,才能真正理解和(或者,就此而言)之间关系DISTINCT
ORDER BY
的混淆。它不同于操作的句法顺序,后者是混淆的主要来源。GROUP BY
在这个例子中,考虑到它的句法接近性,它看起来好像DISTINCT
与 相关,但它实际上是一个在(投影)之后SELECT
应用的运算符。由于 what does(删除重复行)的性质,在操作(包括该子句)之后,行的所有未投影内容都不再可用。根据操作的逻辑顺序(简化): SELECT
DISTINCT
DISTINCT
ORDER BY
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 在这里。生产
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 在这里。错误是:
错误:对于 SELECT DISTINCT,ORDER BY 表达式必须出现在选择列表第 8 行:ORDER BY fname DESC
因为你fname
会赋予什么价值name = A
?A
还是C
?答案将决定您是否会因此得到A
,B
或B
, A
。无法决定。
PostgreSQLDISTINCT ON
现在,正如上面链接的文章中提到的,PostgreSQL 支持一个例外,这偶尔会很有用:(DISTINCT ON
另请参阅这些问题):
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 这里,产生:
id |fname|name
---|-----|----
1 |A |A
3 |B |B
此查询只允许生成 的不同值name
,然后对每个重复行取第一个给定ORDER BY
子句的值,这使得每个不同组的选择是明确的。这可以在其他 RDBMS 中使用窗口函数来模拟。