MySQL-Äquivalent von WITH in oracle


Antworten:


16

Da ist nicht. Sofern (bis) man es entwickelt (MySQL ist Open Source, jeder kann dazu beitragen.)

Das WITHSchlüsselwort ANSI / ISO SQL wird zum Definieren von Common Table Expressions (CTEs) verwendet und vereinfacht komplexe Abfragen mit einer oder mehreren verschachtelten Referenzen. Es ist in Oracle, Postgres, SQL-Server, DB2, aber nicht in MySQL verfügbar.

Die letzte Abfrage kann Verweise enthalten (normalerweise in der FROM Klausel, sie können sich jedoch auch in einem anderen Teil befinden) auf einen oder mehrere der allgemeinen Tabellenausdrücke enthalten. Die Abfrage kann in MySQL mithilfe von abgeleiteten Tabellen (ohne CTEs) geschrieben werden, die Verweise müssen jedoch wiederholt erfolgen.

Beispiel einer albernen Abfrage, die alle in den 50er Jahren und im Monat Juli geborenen Personen und die Anzahl aller im selben Jahr geborenen Personen anzeigt:

WITH a AS
    ( SELECT name, birthdate, YEAR(birthdate) AS birthyear
      FROM persons
      WHERE birthdate >= '1950-01-01' AND birthdate < '1960-01-01' 
    ) 
, b AS
    ( SELECT birthyear, COUNT(*) AS cnt
      FROM a
      GROUP BY birthyear 
    ) 
SELECT a.name, a.birthdate, b.cnt AS number_of_births
FROM a JOIN b
  ON a.birthyear = b.birthyear 
WHERE MONTH(a.birthdate) = 7 ;

In MySQL könnte es so geschrieben werden:

SELECT a.name, a.birthdate, b.cnt AS number_of_births
FROM 
    ( SELECT name, birthdate, YEAR(birthdate) AS birthyear
      FROM persons
      WHERE birthdate >= '1950-01-01' AND birthdate < '1960-01-01' 
    ) AS a 
  JOIN 
    ( SELECT birthyear, COUNT(*) AS cnt
      FROM 
        ( SELECT name, birthdate, YEAR(birthdate) AS birthyear
          FROM persons
          WHERE birthdate >= '1950-01-01' AND birthdate < '1960-01-01' 
        ) AS aa
      GROUP BY birthyear
    ) AS b
  ON a.birthyear = b.birthyear 
WHERE MONTH(a.birthdate) = 7 ;

Beachten Sie die Duplizierung des Codes für die abgeleitete Tabelle a. Bei komplexeren Abfragen müsste Code mehrmals geschrieben werden.


Wäre es nicht besser, Variablen und temporäre Tabellen zu verwenden, um Wiederholungen (doppelten Code) zu vermeiden?
Pacerier

Ich würde mir keine Sorgen um die Vervielfältigung von Code machen, aber aus Performancegründen würde ich auf jeden Fall eine Version mit temporären Tabellen in Betracht ziehen und ausprobieren.
ypercubeᵀᴹ

1
Warum würden Sie sich keine Sorgen um die Vervielfältigung von Code machen? Das ist total chaotisch und un  TROCKEN .
Pacerier

1
@Pacerier DRY ist bei DB-Code nicht immer relevant.
JNK

1
@Pacerier Ich wäre nicht überrascht, wenn es nicht wäre. DB-Engines müssen fundierte Vermutungen anstellen, was am besten funktioniert, und dennoch sicherstellen, dass korrekte Ergebnisse zurückgegeben werden. Temp-Tabellen sind im Allgemeinen in Ordnung, aber DRY führt zu einer schrecklichen Leistung in DBs in anderer Hinsicht, wie benutzerdefinierte Funktionen.
JNK

2

Das wird funktionieren, aber es ist schade, dass die WITH-Klausel nicht den Vorteil bietet, dass dieselbe Abfrage nicht mehrmals ausgeführt werden muss (bei komplexen Abfragen kann dies sehr langsam und für die Datenbank-Engine sehr anstrengend sein; ich habe es gelitten). .

Ich würde vorschlagen, jedes in der ursprünglichen WITH-Klausel definierte SELECT in eine eigene temporäre Tabelle einzufügen und in der Abfrage zu verwenden . In MySQL wird die temporäre Tabelle automatisch gelöscht, sobald die Benutzersitzung endet.

BEARBEITEN:

Ich habe diese Antwort gerade in einem ähnlichen Thread gesehen, der die drei Problemumgehungen von MySQL deutlich macht :

  • TEMPORARY-Tabellen
  • ABGELEITETE Tabellen
  • Inline-Ansichten (effektiv was die WITH-Klausel darstellt - sie sind austauschbar)

/programming//a/1382618/2906290

und ein Beispiel für eine MySQL-Prozedur, die temporäre Tabellen erstellt und löscht, falls Sie Ihre Sitzung fortsetzen und diese Ressourcen freigeben möchten (ich würde es nur als Beispiel für die Syntax verwenden): /programming//a/ 5553145/2906290

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.