SQL Server 2012对ORDER BY使用EXCEPT

Dom*_*bey 4 sql-server

我可以执行这个.

SELECT TOP 10 model, price
FROM PC 
EXCEPT
SELECT TOP 9 model, price
FROM PC ORDER BY price DESC 
Run Code Online (Sandbox Code Playgroud)

但是当我运行它时,我在'Order'附近遇到了语法错误.

SELECT TOP 10 model, price
FROM PC ORDER BY price DESC
EXCEPT
SELECT TOP 9 model, price
FROM PC ORDER BY price DESC 
Run Code Online (Sandbox Code Playgroud)

而我必须这样做.为什么上面的工作没有?

SELECT * FROM
(
SELECT TOP 10 model, price
FROM PC ORDER BY price DESC
EXCEPT
SELECT TOP 9 model, price
FROM PC ORDER BY price DESC
) X
Run Code Online (Sandbox Code Playgroud)

Eri*_*ikE 5

说明

ORDER BY子句在两种情况下是允许的:当a TOP(或OFFSET/FETCH)存在时,以及作为单个查询一起运行的一系列查询/子查询的最外层查询.现在,如您所知,ORDER BY如果没有TOP子句,则无法在内部查询上下文中使用.但另外,当两种情况(TOP与最外层)发生冲突时,最外层的查询上下文优先.

当使用UNION,EXCEPT和时INTERSECT,最外层的查询上下文ORDER BY(预期的位置)是最后一个查询,尽管它适用于整个查询.由于最外层的查询上下文规则优先,因此不允许尝试使用其中一个关键字与其他子查询进行排序.

通过EXCEPT使用派生表将最外层查询上下文移出ed查询,就像您所做的那样,现在允许各个子查询具有各自的ORDER BY子句.

可能的改进

如果您使用的是SQL Server 2012或更高版本,最好只使用OFFSETFETCH关键字来实现您的目标:

SELECT model, price
FROM dbo.PC
ORDER BY price DESC
OFFSET 9 ROWS 
FETCH NEXT 1 ROWS ONLY;
Run Code Online (Sandbox Code Playgroud)

通过这种方式,查询可以更清楚地表达您的意图,您不必复制查询,这些对于将来的维护以及对查看查询的任何未来开发人员的理解而言都是一个巨大的胜利.请记住,我们的代码应按顺序排列:

  1. 正确(以及任何正确定义的表现)
  2. 明确
  3. 简洁
  4. 快速

在这里,清晰度似乎要求使用正确的查询关键字,而不是通过有点hacky(虽然聪明)的方式实现相同的结果.