Co oznacza [OD x, y] w Postgres?

12

Właśnie zaczynam pracę z Postgres. Czytając ten dokument natknąłem się na to zapytanie:

SELECT title, ts_rank_cd(textsearch, query) AS rank
FROM apod, to_tsquery('neutrino|(dark & matter)') query
WHERE query @@ textsearch
ORDER BY rank DESC
LIMIT 10;

Mogę zrozumieć wszystko, co w tym zapytaniu, z wyjątkiem tego: FROM apod, ....

Co to ,znaczy Jestem przyzwyczajony do łączenia, ale nie do wielu FROMinstrukcji oddzielonych przecinkiem.

Szukałem w sieci bezskutecznie. Po przyjrzeniu się i przemyśleniu wydaje mi się, że deklaruje zmienną zwaną zapytaniem, dzięki czemu może jej używać wiele razy. Ale jeśli to prawda, co to ma wspólnego FROM?

andrerpena
źródło

Odpowiedzi:

10

Tworzy to domniemanie CROSS JOIN. To jest składnia SQL-89.

Tutaj używam values(1)i values(2)do tworzenia tabel pseduo (tabel wartości) jedynie dla przykładów. Rzecz po nich t(x), g(y)zwana FROM-Aliasami, znak w nawiasie to alias dla kolumny ( xi yodpowiednio). Równie łatwo możesz utworzyć tabelę, aby to przetestować.

SELECT *
FROM (values(1)) AS t(x), (values(2)) AS g(y)

Oto, jak byś to teraz napisał.

SELECT *
FROM (values(1)) AS t(x)
CROSS JOIN (values(2)) AS g(y);

Stamtąd możesz uczynić to domyślnym INNER JOINpoprzez dodanie warunkowego.

SELECT *
FROM (values(1)) AS t(x)
CROSS JOIN (values(1)) AS g(z)
WHERE x = z;

Lub jawna i nowsza INNER JOINskładnia,

SELECT *
FROM (values(1)) AS t(x)
INNER JOIN (values(1)) AS g(z)
  ON ( x = z );

W twoim przykładzie ..

FROM apod, to_tsquery('neutrino|(dark & matter)') query

Jest to w zasadzie to samo co nowsza składnia,

FROM apod
CROSS JOIN to_tsquery('neutrino|(dark & matter)') AS query

co w rzeczywistości jest w tym przypadku takie samo, ponieważ to_tsquery()zwraca wiersz, a nie zestaw jako,

SELECT title, ts_rank_cd(
  textsearch,
  to_tsquery('neutrino|(dark & matter)')
) AS rank
FROM apod
WHERE to_tsquery('neutrino|(dark & matter)') @@ textsearch
ORDER BY rank DESC
LIMIT 10;

Jednak powyższe może potencjalnie to_tsquery('neutrino|(dark & matter)')wystąpić dwukrotnie, ale w tym przypadku tak się nie dzieje - to_tsqueryjest oznaczone jako STABILNE (weryfikowane za pomocą \dfS+ to_tsquery).

STABLEwskazuje, że funkcja nie może zmodyfikować bazy danych i że podczas skanowania pojedynczej tabeli konsekwentnie zwróci ten sam wynik dla tych samych wartości argumentów, ale jej wynik może ulec zmianie w instrukcjach SQL. Jest to odpowiedni wybór dla funkcji, których wyniki zależą od wyszukiwania w bazie danych, zmiennych parametrów (takich jak bieżąca strefa czasowa) itp. (Jest nieodpowiedni dla wyzwalaczy AFTER, które chcą zapytać o wiersze zmodyfikowane przez bieżące polecenie.) Należy również pamiętać, że rodzina funkcji current_timestamp kwalifikuje się jako stabilna, ponieważ ich wartości nie zmieniają się w ramach transakcji.

Aby uzyskać pełniejsze porównanie różnic między SQL-89 i SQL-92, zobacz także moją odpowiedź tutaj

Evan Carroll
źródło
Dziękuję Ci bardzo. Zaczynam od SQL. To ma sens ,jako połączenie krzyżowe, ponieważ jest to tylko produkt kartezjański i nie ma w tym porównania. Czy możesz po prostu odpowiedzieć na jeszcze 1 pytanie PROSZĘ? co jest t(x)w (values(1)) AS t(x)??
andrerpena
Aktualizacja @andrerpena.
Evan Carroll
1
jesteście najlepsi. Krystalicznie czyste wyjaśnienie. Wielkie dzięki.
andrerpena
Nigdy nie słyszałem terminu „Z aliasu” dla aliasu tabeli . to_tsquery()zwraca wartość, a nie wiersz . I tylko dlatego, że funkcja jest zdefiniowana STABLE, to nie znaczy, planista zapytanie będzie uniknąć ponownej oceny. To możliwe .
Erwin Brandstetter
12

Podręcznik zawiera szczegółowe objaśnienie przecinka na FROMliście w rozdziale Wyrażenia tabelowe :

FROM§ wyprowadza tabeli z jednym lub większą liczbą stolików podanych na liście odniesienia Stół oddzielony przecinkami.

FROM table_reference [, table_reference [, ...]]

Odwołaniem do tabeli może być nazwa tabeli (prawdopodobnie kwalifikowana do schematu) lub tabela pochodna, taka jak podzapytanie, JOINkonstrukcja lub ich złożone kombinacje. Jeśli w FROMklauzuli znajduje się więcej niż jedno odniesienie do tabeli , tabele są łączone krzyżowo (tzn. Powstaje iloczyn kartezjański ich wierszy; patrz poniżej).

Fakt, że odwołania do tabel oddzielone przecinkami zostały zdefiniowane we wcześniejszej wersji standardu SQL niż jawna JOINskładnia, nie powodują, że przecinek jest niepoprawny lub nieaktualny. Użyj jawnej składni sprzężenia, gdy jest to technicznie konieczne (patrz poniżej) lub gdy sprawia, że ​​tekst zapytania jest wyraźniejszy.

Instrukcja ponownie:

FROM T1 CROSS JOIN T2jest równoważne FROM T1 INNER JOIN T2 ON TRUE (patrz poniżej). Jest to również równoważne z FROM T1, T2.

Ale „ekwiwalent” nie oznacza identyczności . Istnieje subtelna różnica, jak ręcznych notatek :

Uwaga:
Ta ostatnia równoważność nie zachowuje się dokładnie, gdy pojawiają się więcej niż dwie tabele, ponieważ JOINwiąże się mocniej niż przecinek. Na przykład FROM T1 CROSS JOIN T2 INNER JOIN T3 ON conditionto nie to samo, FROM T1, T2 INNER JOIN T3 ON conditionponieważ conditionmoże odwoływać się T1w pierwszym przypadku, ale nie w drugim.

To powiązane pytanie pokazuje znaczenie różnicy:

Zasadniczo twoja obserwacja jest dokładnie słuszna:

wydaje mi się, że deklaruje zmienną o nazwie zapytanie, dzięki czemu może jej używać wiele razy.

Dowolną funkcję można wykorzystać jako „funkcję tabeli” na FROMliście. A parametry funkcji mogą odwoływać się do kolumn ze wszystkich tabel po lewej stronie funkcji, ponieważ notacja:

FROM apod, to_tsquery('neutrino|(dark & matter)') query

jest naprawdę równoważny z:

FROM apod CROSS JOIN LATERAL to_tsquery('neutrino|(dark & matter)') AS query

Podręcznik dotyczący zapytań LATERAL:

Pojawiające się funkcje tabeli FROMmogą być również poprzedzone słowem kluczowym LATERAL, ale w przypadku funkcji słowo kluczowe jest opcjonalne ; argumenty funkcji mogą w każdym przypadku zawierać odwołania do kolumn dostarczone przez poprzedzające elementy FROM.

Odważny nacisk moje.

Słowo kluczoweAS to całkowicie opcjonalny szum przed aliasami tabeli (w przeciwieństwie do aliasów kolumn , w których zaleca się, aby nie pomijać, ASaby uniknąć ewentualnych dwuznaczności). Powiązana odpowiedź z więcej:

Erwin Brandstetter
źródło