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

Kam*_*med 64 sql database sql-server sql-server-2012

除非还指定了TOP,OFFSET或FOR XML,否则ORDER BY子句在视图,内联函数,派生表,子查询和公用表表达式中无效.

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

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   
Run Code Online (Sandbox Code Playgroud)

him*_*056 73

您不需要ORDER BY在内部查询后续WHERE子句中使用,因为您已经使用过它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 
Run Code Online (Sandbox Code Playgroud)

  • 不,您*不能*使用ORDER BY对派生表中的行进行排序,原因在于错误消息中给出的原因.结果集中的行顺序最终由外部SELECT中的ORDER BY子句控制,而不是由OVER子句控制.[OVER子句](http://technet.microsoft.com/en-us/library/ms189461.aspx)"指定执行窗口函数计算的*逻辑*顺序".它不对结果集进行排序. (22认同)

Jos*_*ose 27

ORDER BY column OFFSET 0 ROWS
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是它可以工作,这是一个多么奇怪的功能。

一个更大的例子,使用 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
Run Code Online (Sandbox Code Playgroud)

所以我们得到所有结果 MainCol

但结果与MainCol = 1get 排序ColX

结果与MainCol = 0get 排序ColY

  • 任何人都可以提供关于为什么 Microsoft 需要这种荒谬的冗余附加语法的见解吗? (7认同)
  • 好吧,我该死,它确实有效。我讨厌我必须这样做,但我喜欢解决方案如此简单。您在最顶部的代码片段对于我的查询来说是开箱即用的。 (2认同)