我可以执行此操作。
SELECT TOP 10 model, price
FROM PC
EXCEPT
SELECT TOP 9 model, price
FROM PC ORDER BY price DESC
但是当我运行这个时,我在“订单”附近遇到了语法错误。
SELECT TOP 10 model, price
FROM PC ORDER BY price DESC
EXCEPT
SELECT TOP 9 model, price
FROM PC ORDER BY price DESC
而我必须这样做。为什么不进行上述工作?
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
答案 0 :(得分:5)
<强>解释强>
在两种情况下允许使用ORDER BY
子句:当TOP
(或OFFSET/FETCH
)存在时,以及在一系列查询/子查询的最外层查询中,这些查询/子查询一起作为单一查询。现在,如您所知,如果没有ORDER BY
子句,则不能在内部查询上下文中使用TOP
。但另外,当两种情况(TOP
与最外层)发生冲突时,最外层的查询上下文优先。
使用UNION
,EXCEPT
和INTERSECT
时,最需要ORDER BY
的查询上下文是 last 查询,虽然它适用于整个查询。由于最外层的查询上下文规则优先,因此不允许尝试使用其中一个关键字与其他子查询进行排序。
通过使用派生表将最外层查询上下文移出EXCEPT
ed查询,就像您所做的那样,现在允许各个子查询具有各自的ORDER BY
子句。
可能的改进
如果您使用的是SQL Server 2012或更高版本,最好只使用OFFSET
和FETCH
关键字来实现目标:
SELECT model, price
FROM dbo.PC
ORDER BY price DESC
OFFSET 9 ROWS
FETCH NEXT 1 ROWS ONLY;
通过这种方式,查询可以更清楚地表达您的意图,您不必复制查询,这些共同构成了未来维护以及对查询查询的任何未来开发人员的理解。请记住,我们的代码应按顺序排列:
在这里,清晰度似乎要求使用正确的查询关键字,而不是通过有点hacky(虽然聪明)的方式实现相同的结果。