Die ORDER BY-Klausel ist in Ansichten, Inline-Funktionen, abgeleiteten Tabellen, Unterabfragen und allgemeinen Tabellenausdrücken ungültig

75

Die ORDER BY-Klausel ist in Ansichten, Inline-Funktionen, abgeleiteten Tabellen, Unterabfragen und allgemeinen Tabellenausdrücken ungültig, sofern nicht auch TOP, OFFSET oder FOR XML angegeben ist.

Beim Versuch, die folgende Abfrage auszuführen, wird der oben genannte Fehler angezeigt. Kann mir bitte jemand einen Blick darauf werfen und mir sagen, was ich hier falsch mache?

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   
Kamran Ahmed
quelle
2
Die Reihenfolge von sollte außerhalb der Unterabfrage liegen, wählen Sie, wie der Fehler sagte
Daniele

Antworten:

86

Sie müssen die ORDER BYinnere Abfrage nach der WHEREKlausel nicht verwenden, da Sie sie bereits in verwendet haben 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 
Himanshu Jansari
quelle
25
Nein, Sie können ORDER BY nicht verwenden, um Zeilen in der abgeleiteten Tabelle aus dem in der Fehlermeldung angegebenen Grund zu sortieren. Die Reihenfolge der Zeilen in der Ergebnismenge wird letztendlich durch eine ORDER BY-Klausel im äußeren SELECT gesteuert, nicht durch die OVER-Klausel. Die OVER-Klausel "gibt die logische Reihenfolge an, in der die Fensterfunktionsberechnung durchgeführt wird". Die Ergebnismenge wird nicht sortiert.
Mike Sherrill 'Cat Recall'
10
ORDER BY column OFFSET 0 ROWS

Überraschenderweise funktioniert es, was für ein seltsames Feature.

Ein größeres Beispiel mit einem CTE als Möglichkeit, eine lange Abfrage vorübergehend zu "speichern", um sie später neu zu bestellen:

;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

So erhalten wir alle Ergebnisse sortiert nach MainCol

Aber die Ergebnisse mit MainCol = 1werden von bestelltColX

Und die Ergebnisse mit MainCol = 0werden von bestelltColY

Jose V.
quelle
4
Kann jemand einen Einblick geben, warum Microsoft diese absurd redundante zusätzliche Syntax benötigen würde?
Black