Czy w Oracle jest odpowiednik MySQL klauzuli WITH?
Czy w Oracle jest odpowiednik MySQL klauzuli WITH?
Odpowiedzi:
Tam nie ma. O ile (dopóki) się go nie rozwinie (MySQL jest oprogramowaniem typu open source, każdy może wnieść swój wkład).
WITH
Słowo kluczowe ANSI / ISO SQL służy do definiowania wspólnych wyrażeń tabelowych (CTE) i upraszcza złożone zapytania za pomocą jednego lub kilku zagnieżdżonych odniesień. Jest dostępny w Oracle, Postgres, SQL-Server, DB2, ale nie w MySQL.
Ostatnie zapytanie może zawierać odwołania (zwykle w FROM
klauzuli, ale mogą znajdować się w dowolnej innej części) do dowolnego z typowych wyrażeń tabelowych, jeden lub więcej razy. Zapytanie można zapisać (bez CTE) w MySQL przy użyciu tabel pochodnych, ale odwołania należy powtarzać.
Przykład głupiego zapytania pokazującego wszystkie osoby urodzone w latach 50. i w lipcu oraz liczbę wszystkich osób urodzonych w tym samym roku:
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 ;
W MySQL można go zapisać jako:
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 ;
Zwróć uwagę na powielanie kodu dla tabeli pochodnej a
. W bardziej złożonych zapytaniach kod musiałby być napisany wiele razy.
To zadziała, ale szkoda, że nie zapewni korzyści wynikających z użycia klauzuli WITH, czyli nie wykona tego samego zapytania kilka razy (przy złożonych zapytaniach może być naprawdę powolne i bardzo wymagające dla silnika bazy danych; cierpiałem) .
Sugerowałbym wstawienie każdego SELECT zdefiniowanego w oryginalnej klauzuli WITH do własnej tabeli tymczasowej i użycie ich w zapytaniu . W MySQL tabela tymczasowa opuści się po zakończeniu sesji użytkownika.
EDYTOWAĆ:
Właśnie widziałem tę odpowiedź w podobnym wątku, który wyraźnie pokazuje 3 obejścia MySQL :
/programming//a/1382618/2906290
oraz przykład procedury MySQL, która tworzy i upuszcza tabele tymczasowe na wypadek, gdybyś kontynuował sesję i chciałby zwolnić te zasoby (użyłbym jej tylko jako przykładu składni): /programming//a/ 5553145/2906290