Odpowiednik MySQL Z w wyroczni

12

Czy w Oracle jest odpowiednik MySQL klauzuli WITH?

Neeru Sharma
źródło

Odpowiedzi:

16

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).

WITHSł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 FROMklauzuli, 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.

ypercubeᵀᴹ
źródło
Aby uniknąć powtórzeń (powielania kodu), czy nie byłoby lepiej używać zmiennych i tabel tymczasowych?
Pacerier
Nie martwiłbym się powielaniem kodu, ale z pewnością wziąłbym pod uwagę wydajność i wypróbowałbym wersję z tabelami tymczasowymi.
ypercubeᵀᴹ
1
Dlaczego mówisz, że nie przejmowałbyś się powielaniem kodu? To jest całkowicie niechlujne i un  DRY .
Pacerier
1
@Pacerier DRY nie zawsze dotyczy kodu DB.
JNK
1
@Pacerier Nie byłbym zaskoczony, gdyby tak nie było. Silniki DB muszą zgadywać, co będzie działać najlepiej, jednocześnie gwarantując prawidłowe wyniki. Tabele temperatur ogólnie są w porządku, ale DRY prowadzi do strasznej wydajności w bazach danych pod innymi względami, takimi jak funkcje zdefiniowane przez użytkownika.
JNK
2

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 :

  • Tabele TEMPORARY
  • Tabele DERIVED
  • widoki wbudowane (faktycznie to, co reprezentuje klauzula WITH - są one wymienne)

/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

Raúl Moreno
źródło