46 Stimmen

Reihenfolge der Ausführung der SQL-Abfrage

Ich bin verwirrt mit der Reihenfolge der Ausführung dieser Abfrage, bitte erklären Sie mir das. Ich bin verwirrt, wenn die Verknüpfung angewendet wird, die Funktion aufgerufen wird, eine neue Spalte mit dem Fall hinzugefügt wird und wenn die Seriennummer hinzugefügt wird. Bitte erklären Sie mir die Reihenfolge der Ausführung all dessen.

select Row_number() OVER(ORDER BY (SELECT 1))  AS 'Serial Number', 
    EP.FirstName,Ep.LastName,[dbo].[GetBookingRoleName](ES.UserId,EP.BookingRole) as RoleName,  
    (select top 1 convert(varchar(10),eventDate,103)from [3rdi_EventDates] where EventId=13) as EventDate,
    (CASE [dbo].[GetBookingRoleName](ES.UserId,EP.BookingRole)  
            WHEN    '90 Day Client' THEN 'DC'
            WHEN    'Association Client'  THEN  'DC'
            WHEN    'Autism Whisperer'    THEN  'DC'
            WHEN    'CampII'             THEN   'AD' 
            WHEN    'Captain'              THEN 'AD' 
            WHEN    'Chiropractic Assistant' THEN 'AD'
            WHEN    'Coaches'               THEN 'AD'
            END) as Category from [3rdi_EventParticipants] as EP  
    inner join [3rdi_EventSignup] as ES on EP.SignUpId = ES.SignUpId  
    where EP.EventId = 13
    and userid in (  
    select distinct userid from userroles  
    --where roleid not in(6,7,61,64) and roleid not in(1,2))  
    where roleid not in(19, 20, 21, 22) and roleid not in(1,2))

Dies ist die Funktion, die in der obigen Abfrage aufgerufen wird.

CREATE function [dbo].[GetBookingRoleName]  
(  
 @UserId as integer,
 @BookingId as integer
)  
RETURNS varchar(20)  
as  
begin  
declare @RoleName varchar(20)  

if @BookingId = -1
Select Top 1 @RoleName=R.RoleName From UserRoles UR inner join Roles R on UR.RoleId=R.RoleId Where UR.UserId=@UserId and R.RoleId not in(1,2)  
else
Select @RoleName= RoleName From Roles where RoleId = @BookingId

return @RoleName  
end

83voto

Randy Minder Punkte 45277

Abfragen werden im Allgemeinen in der folgenden Reihenfolge verarbeitet (SQL Server). Ich habe keine Ahnung, ob andere RDBMS das auch so machen.

FROM [MyTable]
    ON [MyCondition]
  JOIN [MyJoinedTable]
 WHERE [...]
 GROUP BY [...]
HAVING [...]
SELECT [...]
 ORDER BY [...]

67voto

Remus Rusanu Punkte 280155

SQL hat keine Reihenfolge der Ausführung. Es ist eine deklarative Sprache. Dem Optimierer steht es frei, jede beliebige Reihenfolge zu wählen, die er für geeignet hält, um die beste Ausführungszeit zu erzielen. Bei einer beliebigen SQL-Abfrage ist es im Grunde unmöglich, so zu tun, als ob man die Ausführungsreihenfolge kennt. Wenn man detaillierte Informationen über das betroffene Schema (genaue Definition der Tabellen und Indizes) und die geschätzten Kardinalitäten (Größe der Daten und Selektivität der Schlüssel) hinzufügt, kann man eine erraten bei der wahrscheinlichen Ausführungsanordnung.

Letztendlich ist die einzig richtige "Reihenfolge" diejenige, die im eigentlichen Ausführungsplan beschrieben ist. Siehe Anzeige von Ausführungsplänen mit Hilfe von SQL Server Profiler-Ereignisklassen y Grafische Anzeige von Ausführungsplänen (SQL Server Management Studio) .

Eine ganz andere Frage ist jedoch, wie sich Abfragen, Unterabfragen und Ausdrücke in die "Gültigkeit" projizieren lassen. Wenn Sie zum Beispiel einen Alias-Ausdruck in der SELECT-Projektionsliste haben, können Sie den Alias dann in der WHERE-Klausel verwenden? Etwa so:

SELECT a+b as c
FROM t
WHERE c=...;

Ist die Verwendung von c Alias in der Where-Klausel gültig? Die Antwort lautet NEIN. Abfragen bilden einen Syntaxbaum, und ein unterer Zweig des Baums kann nicht auf etwas verweisen, das weiter oben im Baum definiert ist. Dies hat nicht unbedingt etwas mit der Reihenfolge der "Ausführung" zu tun, sondern ist eher ein Problem der Syntaxanalyse. Es ist vergleichbar mit dem Schreiben dieses Codes in C#:

void Select (int a, int b)
{
   if (c = ...) then {...}
   int c = a+b;
}

Genau wie in C# lässt sich dieser Code nicht kompilieren, weil die Variable c verwendet wird, bevor es definiert ist, wird der obige SELECT nicht richtig kompiliert, weil der Alias c in der Baumstruktur weiter unten referenziert wird als tatsächlich definiert ist.

Im Gegensatz zu den bekannten Regeln für das Parsen von C/C#-Sprachen sind die SQL-Regeln für den Aufbau des Abfragebaums leider etwas esoterisch. Es gibt eine kurze Erwähnung davon in Verarbeitung einzelner SQL-Anweisungen aber eine ausführliche Diskussion darüber, wie sie erstellt werden und welche Reihenfolge gültig ist und welche nicht, kenne ich keine Quelle. Ich sage nicht, dass es keine guten Quellen gibt, ich bin sicher, dass einige der guten SQL-Bücher dieses Thema behandeln.

Beachten Sie, dass die Reihenfolge des Syntaxbaums nicht mit der visuellen Reihenfolge des SQL-Textes übereinstimmt. Zum Beispiel ist die ORDER BY-Klausel normalerweise die letzte im SQL-Text, aber als Syntaxbaum steht sie über allem anderen (sie sortiert die Ausgabe des SELECTs, liegt also sozusagen über den SELECT-Spalten) und ist als solches est gültig, um auf die c alias:

SELECT a+b as c
FROM t
ORDER BY c;

Aktualisiert

Tatsächlich gibt es dies: Logische Verarbeitungsreihenfolge der SELECT-Anweisung

Die folgenden Schritte zeigen die logische Verarbeitungsreihenfolge, oder Bindungsreihenfolge, für eine SELECT-Anweisung. Diese Reihenfolge bestimmt, wann die Objekte, die in einem Schritt definierten Objekte für die Klauseln in den nachfolgenden Schritten zur Verfügung gestellt werden. Für zum Beispiel, wenn der Abfrageprozessor auf die Tabellen oder Views binden (zugreifen) die in der FROM-Klausel definiert sind, werden diese Objekte und ihre Spalten für alle nachfolgenden für alle nachfolgenden Schritte zur Verfügung. Umgekehrt, da die SELECT-Klausel Schritt 8 ist, werden alle Spaltenalias oder abgeleitete Spalten, die in dieser Klausel definiert sind nicht von den vorangehenden Klauseln referenziert werden. Sie können jedoch durch nachfolgende Klauseln referenziert werden, wie wie die ORDER BY-Klausel. Beachten Sie, dass die tatsächliche physische Ausführung der Anweisung durch die Abfrage bestimmt wird Prozessor bestimmt wird, und die Reihenfolge kann von dieser Liste abweichen kann.

  1. VON
  2. ON
  3. JOIN
  4. WHERE
  5. GROUP BY
  6. MIT WÜRFEL oder MIT ROLLUP
  7. HABEN
  8. SELECT
  9. DISTINCT
  10. ORDER BY
  11. TOP

13voto

nybon Punkte 7875

SQL-Abfragen sind nicht zwingend, sondern deklarativ. Sie haben also keine Ahnung, welche Anweisung zuerst ausgeführt wird, aber da SQL von SQL-Abfrageprogrammen ausgewertet wird, folgen die meisten SQL-Programme einem ähnlichen Prozess, um die Ergebnisse zu erhalten. Möglicherweise müssen Sie verstehen, wie die Abfrage-Engine intern arbeitet, um das Verhalten der SQL-Ausführung zu verstehen.

Julia Evens hat einen großartigen Beitrag verfasst, in dem sie dies erklärt, es lohnt sich, ihn zu lesen:

https://jvns.ca/blog/2019/10/03/sql-queries-don-t-start-with-select/

enter image description here

9voto

IamIC Punkte 16837

SQL ist eine deklarative Sprache, d. h. sie sagt der SQL-Engine, was sie tun soll, nicht wie. Dies steht im Gegensatz zu einer imperativen Sprache wie C, in der klar festgelegt ist, wie etwas zu tun ist.

Dies bedeutet, dass nicht alle Anweisungen wie erwartet ausgeführt werden. Besonders zu beachten sind boolesche Ausdrücke, die möglicherweise nicht wie geschrieben von links nach rechts ausgewertet werden. Der folgende Code wird beispielsweise nicht garantiert ohne einen Fehler bei der Division durch Null ausgeführt:

SELECT 'null' WHERE 1 = 1 OR 1 / 0 = 0

Der Grund dafür ist, dass der Abfrageoptimierer den besten (effizientesten) Weg zur Ausführung einer Anweisung wählt. Das bedeutet, dass z. B. ein Wert geladen und gefiltert werden kann, bevor ein Transformationsprädikat angewendet wird, was zu einem Fehler führt. Siehe den zweiten Link oben für ein Beispiel

Siehe: aquí y aquí .

4voto

Conrad Frix Punkte 50686

Die "Reihenfolge der Ausführung" ist wahrscheinlich ein schlechtes mentales Modell für SQL-Abfragen. Es ist schwer, eine einzige Abfrage zu schreiben, die tatsächlich von der Ausführungsreihenfolge abhängt (und das ist auch gut so). Stattdessen sollten Sie sich vorstellen, dass alle Join- und Where-Klauseln gleichzeitig ausgeführt werden (fast wie eine Vorlage)

Das heißt, Sie könnten die Anzeige der Ausführungspläne die Ihnen einen Einblick in das Thema geben sollte.

Da jedoch nicht klar ist, warum Sie die Reihenfolge der Ausführung wissen wollen, vermute ich, dass Sie versuchen, ein mentales Modell für diese Abfrage zu erhalten, damit Sie es in irgendeiner Weise beheben können. So würde ich Ihre Abfrage "übersetzen". Obwohl ich mit dieser Art von Analyse gute Erfahrungen gemacht habe, gibt es eine gewisse Grauzone, was die Genauigkeit angeht.

VON UND WO-KLAUSEL

  • Geben Sie mir alle Zeilen der Veranstaltungsteilnehmer. from [3rdi_EventParticipants

  • Geben Sie mir auch alle Event-Anmeldezeilen, die mit den Event-Teilnehmerzeilen auf SignUpID übereinstimmen. inner join 3rdi_EventSignup] as ES on EP.SignUpId = ES.SignUpId

  • Aber nur für Veranstaltung 13 EP.EventId = 13

  • Und nur dann, wenn die Benutzer-ID einen Eintrag in der Tabelle "Benutzerrollen" hat und die Rollen-ID nicht in 1,2,19,20,21,22 enthalten ist userid in ( select distinct userid from userroles --where roleid not in(6,7,61,64) and roleid not in(1,2)) where roleid not in(19, 20, 21, 22) and roleid not in(1,2))

SELECT CLAUSE

  • Geben Sie mir für jede der Zeilen eine eindeutige ID Row_number() OVER(ORDER BY (SELECT 1)) AS 'Serial Number',

  • Die Teilnehmer Vorname EP.FirstName

  • Die Teilnehmer Nachname Ep.LastName

  • Der Name der Buchungsrolle GetBookingRoleName

  • Suchen Sie in den Ereignisdaten nach dem ersten Ereignisdatum mit EventId = 13, das Sie finden (select top 1 convert(varchar(10),eventDate,103)from [3rdi_EventDates] where EventId=13) as EventDate

  • Übersetzen Sie schließlich den GetBookingRoleName in Category. Ich habe keine Tabelle dafür, also werde ich sie manuell zuordnen (CASE [dbo].[GetBookingRoleName](ES.UserId,EP.BookingRole) WHEN '90 Day Client' THEN 'DC' WHEN 'Association Client' THEN 'DC' WHEN 'Autism Whisperer' THEN 'DC' WHEN 'CampII' THEN 'AD' WHEN 'Captain' THEN 'AD' WHEN 'Chiropractic Assistant' THEN 'AD' WHEN 'Coaches' THEN 'AD' END) as Category

Deshalb hier ein paar Anmerkungen. Wenn Sie TOP auswählen, ordnen Sie nicht nach irgendetwas. Wahrscheinlich sollten Sie dort na order by eingeben. Sie könnten das auch einfach in Ihre from-Klausel einfügen, z. B.

from [3rdi_EventParticipants] as EP  
    inner join [3rdi_EventSignup] as ES on EP.SignUpId = ES.SignUpId,   
       (select top 1 convert(varchar(10),eventDate,103)
       from [3rdi_EventDates] where EventId=13
       Order by eventDate) dates

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X