ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效

Posted

技术标签:

【中文标题】ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效【英文标题】:The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions 【发布时间】:2013-08-04 13:57:35 【问题描述】:

ORDER BY 子句在视图、内联函数、派生中无效 表、子查询和公用表表达式,除非 TOP、OFFSET 或 FOR XML 也被指定。

我在尝试执行以下查询时遇到上述错误。任何人都可以看看并告诉我我在这里做错了什么吗?

SELECT 
    * 
FROM (
    SELECT 
        Stockmain.VRNOA, 
        item.description as item_description, 
        party.name as party_name, 
        stockmain.vrdate, 
        stockdetail.qty, 
        stockdetail.rate, 
        stockdetail.amount, 
        ROW_NUMBER() OVER (ORDER BY VRDATE) AS RowNum
    FROM StockMain 
    INNER JOIN StockDetail 
        ON StockMain.stid = StockDetail.stid 
    INNER JOIN party 
        ON party.party_id = stockmain.party_id 
    INNER JOIN item 
        ON item.item_id = stockdetail.item_id 
    WHERE stockmain.etype='purchase' 
    ORDER BY VRDATE DESC
) AS MyDerivedTable
WHERE 
    MyDerivedTable.RowNum BETWEEN 1 and 5   

【问题讨论】:

order by 应该在子查询选择之外,如错误所述 【参考方案1】:

您不需要在WHERE 子句之后的内部查询中使用ORDER BY,因为您已经在ROW_NUMBER() OVER (ORDER BY VRDATE DESC) 中使用了它。

SELECT 
    * 
FROM (
    SELECT 
        Stockmain.VRNOA, 
        item.description as item_description, 
        party.name as party_name, 
        stockmain.vrdate, 
        stockdetail.qty, 
        stockdetail.rate, 
        stockdetail.amount, 
        ROW_NUMBER() OVER (ORDER BY VRDATE DESC) AS RowNum  --< ORDER BY
    FROM StockMain 
    INNER JOIN StockDetail 
        ON StockMain.stid = StockDetail.stid 
    INNER JOIN party 
        ON party.party_id = stockmain.party_id 
    INNER JOIN item 
        ON item.item_id = stockdetail.item_id 
    WHERE stockmain.etype='purchase' 
) AS MyDerivedTable
WHERE 
    MyDerivedTable.RowNum BETWEEN 1 and 5 

【讨论】:

不,由于错误消息中给出的原因,您不能使用 ORDER BY 对派生表中的行进行排序。结果集中的行顺序最终由外部 SELECT 中的 ORDER BY 子句控制,而不是由 OVER 子句控制。 OVER clause“指定执行窗口函数计算的逻辑顺序”。它不对结果集进行排序。【参考方案2】:
ORDER BY column OFFSET 0 ROWS

令人惊讶地使它工作,多么奇怪的功能。

一个更大的例子,使用 CTE 作为临时“存储”长查询以便稍后重新排序的一种方式:

;WITH cte AS (
    SELECT .....long select statement here....
)

SELECT * FROM 
(
    SELECT * FROM 
    ( -- necessary to nest selects for union to work with where & order clauses
        SELECT * FROM cte WHERE cte.MainCol= 1 ORDER BY cte.ColX asc OFFSET 0 ROWS 
    ) first
    UNION ALL
    SELECT * FROM 
    (  
        SELECT * FROM cte WHERE cte.MainCol = 0 ORDER BY cte.ColY desc OFFSET 0 ROWS 
    ) last
) as unionized
ORDER BY unionized.MainCol desc -- all rows ordered by this one
OFFSET @pPageSize * @pPageOffset ROWS -- params from stored procedure for pagination, not relevant to example
FETCH FIRST @pPageSize ROWS ONLY -- params from stored procedure for pagination, not relevant to example

所以我们得到所有按MainCol排序的结果

MainCol = 1 的结果由ColX 排序

MainCol = 0 的结果由ColY 排序

【讨论】:

谁能提供一下关于微软为什么需要这种荒谬的冗余附加语法的见解? 好吧,我会被诅咒的,它确实有效。我讨厌我必须这样做,但我喜欢解决方案如此简单。您在最顶部的 sn-p 对我的查询开箱即用。

以上是关于ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效的主要内容,如果未能解决你的问题,请参考以下文章

sqlserver 创建视图失败,原因:ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效

SQL Server查询错误-ORDER BY子句在视图中无效

SQL Server 查询错误 -ORDER BY 子句在视图中无效

子查询中的 Order By 的 SQL 错误

使用Union All 和Order By In View?

oracle不可以用order by么