Ist es möglich, eine berechnete Spalte zu bestellen, ohne sie in die Ergebnismenge aufzunehmen?

Ich habe diese Frage:

SELECT Column1, Column2, Column3, /* computed column */ AS SortColumn FROM Table1 ORDER BY SortColumn 

SortColumn dient keinem anderen Zweck, um eine Reihenfolge für die sorting der Ergebnismenge zu definieren. So möchte ich es in der Ergebnismenge weglassen, um die Größe der an den Client gesendeten data zu verringern. Das folgende scheitert …

 SELECT Column1, Column2, Column3 FROM ( SELECT Column1, Column2, Column3, /* computed column */ AS SortColumn FROM Table1 ORDER BY SortColumn ) AS SortedTable1 

… durch:

Msg 1033, Stufe 15, Staat 1

Die ORDER BY-Klausel ist in Sichten, Inline-functionen, abgeleiteten Tabellen, Unterabfragen und gängigen Tabellenausdrücken ungültig, es sei denn, TOP oder FOR XML ist ebenfalls angegeben.

Also gibt es diese hackige Lösung:

 SELECT Column1, Column2, Column3 FROM ( SELECT TOP /* very high number */ Column1, Column2, Column3, /* computed column */ AS SortColumn FROM Table1 ORDER BY SortColumn ) AS SortedTable1 

Gibt es eine saubere Lösung, die mir nicht bekannt ist, denn das klingt nicht wie ein seltenes Szenario?


Bearbeiten: Die bereits erteilten Lösungen funktionieren in der Tat für die Abfrage, auf die ich hingewiesen habe. Leider habe ich ein wichtiges Detail ausgelassen: Die (bereits vorhandene) Abfrage besteht aus zwei SELECT mit einer UNION dazwischen, die die Sache ziemlich verändert (wieder vereinfacht und hoffentlich nicht zu vereinfacht):

 SELECT Column1, Column2, Column3 FROM Table1 UNION ALL SELECT Column1, Column2, Column3 FROM Table1 ORDER BY /* computed column */ 

Msg 104, Stufe 16, Zustand 1

ORDER BY-Elemente müssen in der Auswahlliste erscheinen, wenn die statement einen UNION-, INTERSECT- oder EXCEPT-Operator enthält.

Also diese Fehlermeldung sagt deutlich, dass ich die berechnete Spalte in beide Auswahllisten setzen muss. So sind wir also wieder mit der Unterabfrage-Lösung, die nicht zuverlässig funktioniert, wie in den Antworten darauf hingewiesen wird.

Wenn, aus welchem ​​Grund auch immer, es nicht praktisch ist, die Berechnung in der ORDER BY zu tun, können Sie etwas ganz Ähnliches zu Ihrem Versuch machen:

 SELECT Column1, Column2, Column3 FROM ( SELECT Column1, Column2, Column3, /* computed column */ AS SortColumn FROM Table1 ) AS SortedTable1 ORDER BY SortColumn 

Beachten Sie, dass alles, was hier geändert wird, dass die ORDER BY auf die äußere Abfrage angewendet wird. Es ist vollkommen gültig, um Spalten in der ORDER BY zu verweisen, die nicht in der SELECT Klausel erscheinen.

Sie müssen nicht eine berechnete Spalte in der select-statement haben, um sie in einer Reihenfolge zu verwenden

 SELECT Column1, Column2, Column3 FROM Table1 ORDER BY /* computed column */ 

Wenn Sie es mit UNION tun müssen, dann tun Sie die UNION in einem cte, und die Reihenfolge von in der Auswahl, um sicherzustellen, dass alle Spalten, die Sie benötigen, um die Berechnung in der CTE

 WITH src AS ( SELECT Column1, Column2, Column3, ColumnNeededForOrderBy FROM Table1 UNION ALL SELECT Column1, Column2, Column3, ColumnNeededForOrderBy FROM Table2 ) SELECT Column1, Column2, Column3 FROM src ORDER BY /* computed column */ 

Setzen Sie einfach den Ausdruck in die order by :

 SELECT Column1, Column2, Column3, FROM Table1 ORDER BY <computed column> 

Der Grund dafür ist verboten, dass die Bestellung der äußeren Auswahl nichts mit der Bestellung der inneren Auswahl zu tun hat – nicht durch Vertrag. Also, wenn Sie die order by ohne eine top Klausel verwenden, sind Sie offensichtlich einen Fehler machen. Durch die Verwendung von top wie du es tust, versteckst du einfach den Fehler, aber du hast immer noch den gleichen Fehler.

Ihr Hack funktioniert nur, weil der Motor die Bestellung bewahrt hat – aber das ist nicht gegeben, und es gibt keine Möglichkeit, das zu erzwingen (außer bei der order by in der äußeren Abfrage). Zum Beispiel kann eine andere Indexnutzung oder parallele Ausführung Ihre data verschlüsseln.

Also nein, es gibt keinen anderen path – Sie müssen in der äußeren Abfrage order by , und das erfordert, dass Sie die Spalte ausgeben, die Sie in der Unterabfrage sortieren möchten. Und wenn du nicht benutzt hast, ist es nicht so, dass es einen Unterschied macht – du brauchst es nicht in der äußeren Auswahl zu wählen, nur die innere. Und nur die äußere auswahl wird an den client geschickt 🙂

Der einzige Ort für einen ORDER BY ist die äußerste Aussage.

Natürlich gibt es exceptionn: Wenn Sie zum Beispiel den TOP Eintrag für eine gefilterte list benötigen (zB der letzte gültige Wert zu einem bestimmten date). Aber in diesen Fällen müssen Sie ORDER BY mit TOP kombinieren.

Nur die äußerste ORDER BY wird die list sortieren, die du bekommst.

Nach dem Bearbeiten sieht das so aus, was du brauchst

 SELECT Column1, Column2, Column3 FROM ( SELECT Column1, Column2, Column3 FROM Table1 UNION ALL SELECT Column1, Column2, Column3 FROM Table1 ) ORDER BY /* computed column */