it-swarm.com.de

Erläutern Sie eine OVER-Klausel

Ich habe eine prägnante TSQL-Anweisung gesehen, die eine Zeichenfolge effektiv in ihre konstituierenden Zeichen aufteilt, eines pro Zeile, um den Wert ascii für jedes Zeichen auszuwerten.

Wenn ich die Abfrage richtig und effektiv lese, werden 3 CTEs verwendet, um eine Tabelle mit 1 Spalte mit 10.000 Zeilen mit dem Wert '0' zu erstellen.

Ein vierter CTE ist wie folgt definiert:

cteTally(n) AS(
    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) n 
    FROM E4
)

Anschließend wird dieser CTE mit einer Tabelle verbunden, die eine Spalte mit den interessierenden Zeichenfolgen mit dem folgenden select enthält:

SELECT n, SUBSTRING(LastName, n, 1), ASCII( SUBSTRING(LastName, n, 1))

Das heißt, Zeilennummer n, dann das n-te Zeichen in Nachname, dann der ASCII-Wert dieses Zeichens.

Meine Fragen beziehen sich auf die over -Klausel im obigen CTE.

Was genau macht es im Wesentlichen?

Wenn wir row_number aus 10.000 identischen Zeilen abfragen, warum brauchen wir überhaupt eine order by - Klausel? Warum wird die order by In eine over -Klausel und nicht als order by - Klausel für die select -Anweisung eingefügt - insbesondere als over -Klausel Gibt nicht einmal eine Partition an? (Ich nehme an, dies bedeutet, dass das Fenster, über das row_number Arbeitet, die vollen 10.000 Zeilen umfasst?) Und was bedeutet es, nach select null Zu bestellen?

7

ROW_NUMBER () ist eine Ranking-Fensterfunktion, und Ranking-Fensterfunktionen erfordern eine obligatorische ORDER BY-Klausel. Wenn Sie versuchen, es ohne ORDER BY zu schreiben, wird ein Syntaxfehler angezeigt.

SELECT ROW_NUMBER() OVER()
FROM (VALUES ('A'), ('B'), ('C')) AS X(Y);
-- Msg 4112, Level 15, State 1, Line 1 
-- The function 'ROW_NUMBER' must have an OVER clause with ORDER BY.

Der Trick mit der Unterabfrage wurde von jemandem entdeckt, der darüber als Leistungsoptimierung gebloggt hat. SQL Server führt immer eine Sortieroperation aus, da Konstanten für die ORDER BY-Klausel nicht zulässig sind:

SELECT ROW_NUMBER() OVER(ORDER BY NULL)
FROM (VALUES ('A'), ('B'), ('C')) AS X(Y);
-- Msg 5309, Level 16, State 1, Line 1
-- Windowed functions, aggregates and NEXT VALUE FOR functions 
-- do not support constants as ORDER BY clause expressions.

Und Ganzzahlen, die als Indizes behandelt werden, sind es auch nicht:

SELECT ROW_NUMBER() OVER(ORDER BY 1)
FROM (VALUES ('A'), ('B'), ('C')) AS X(Y);
-- Msg 5308, Level 16, State 1, Line 1
-- Windowed functions, aggregates and NEXT VALUE FOR functions 
-- do not support integer indices as ORDER BY clause expressions.

Es stellt sich heraus, dass Sie diese Einschränkung aufgrund eines Fehlers im Code umgehen können, indem Sie eine Unterabfrage verwenden, die aus irgendeinem Grund zulässig ist, und den Sortieroperator entfernen.

SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 1))
FROM (VALUES ('A'), ('B'), ('C')) AS X(Y);

(No Sort Operator

Sie können eine beliebige Konstante in der Unterabfrage verwenden. NULL erinnert wahrscheinlich an die Gewohnheit, SELECT NULL in EXISTS-Prädikaten zu verwenden, die in der frühen Geschichte von SQL Server einen Leistungseinfluss im Gegensatz zu * oder einem anderen Spaltenausdruck hatten Der Optimierer war nicht klug genug, um ihn zu ignorieren.

HTH

[~ # ~] update [~ # ~] @ Erik-Darling kommentierte, dass Sie es auch umgehen können, indem Sie berechnete Ausdrücke verwenden:

You can do SELECT ROW_NUMBER() OVER (ORDER BY 1/0);
8
SQLRaptor

Die OVER-Klausel legt die Reihenfolge (und Partitionierung, wenn PARTITION BY enthalten ist) des Zeilensatzes fest, bevor die ausgewählte Fensterfunktion angewendet wird. Da Sie mehrere Fensterfunktionen in einer einzigen Abfrage verwenden können, erfordert jede eine eigene Partitionierung und Reihenfolge, um sicherzustellen, dass die Daten wie gewünscht zurückgegeben werden.

In Ihrem Beispiel wird ROW_NUMBER () verwendet, um eine fortlaufende Zeilennummer für jede Zeile im CTE zu generieren. SELECT NULL wird verwendet, da keine bestimmte Reihenfolge erforderlich ist, für eine Fensterfunktion jedoch eine ORDER BY-Klausel erforderlich ist.

Eine andere Möglichkeit, dasselbe zu erreichen, wäre die Verwendung einer IDENTITY-Spalte, die andere Auswirkungen hat und Änderungen an einer vorhandenen Tabelle oder der Erstellung einer temporären Tabelle erfordert. Mit der Fensterfunktion ROW_NUMBER in einem CTE kann diese Identität im laufenden Betrieb generiert werden.

So beantworten Sie Ihre spezielle Frage:

Was genau macht es im Wesentlichen?

Es ordnet die Zeilen in E4 'zufällig' an, bevor die Fensterfunktion ROW_NUMBER () auf diese Ergebnismenge angewendet wird, um eine Liste von Zeilennummern zu erstellen, die der Anzahl der Zeilen in E4 entspricht. OVER kann übersetzt werden als "Holen Sie sich eine Ergebnismenge mit dieser Reihenfolge und Partitionierung und wenden Sie diese Fensterfunktion (OVER) auf diese Ergebnismenge an, unabhängig von der Reihenfolge in der SELECT-Hauptanweisung."

Weitere Informationen: OVER-Klausel

4
HandyD