Apa yang dimaksud [FROM x, y] di Postgres?

12

Saya baru memulai dengan Postgres. Membaca dokumen ini saya menemukan pertanyaan ini:

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;

Aku bisa mengerti segala sesuatu dalam query ini, kecuali untuk ini: FROM apod, ....

Apa artinya ini ,? Saya terbiasa bergabung tetapi tidak ke beberapa FROMpernyataan yang dipisahkan oleh koma.

Saya mencari di internet tanpa hasil. Setelah melihatnya dan berpikir, menurut saya ia mendeklarasikan variabel yang disebut kueri sehingga dapat menggunakannya beberapa kali. Tetapi jika ini benar, apa hubungannya dengan FROM?

andrerpena
sumber

Jawaban:

10

Itu menciptakan implisit CROSS JOIN. Ini adalah sintaks SQL-89.

Di sini saya menggunakan values(1)dan values(2)membuat tabel pseduo (tabel nilai) hanya untuk contoh. Hal setelah mereka t(x), dan g(y)disebut DARI-Alias karakter di dalam tanda kurung adalah alias untuk kolom ( xdan ymasing - masing). Anda bisa dengan mudah membuat tabel untuk menguji ini.

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

Beginilah cara Anda menulisnya sekarang.

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

Dari sana Anda dapat menjadikan ini suatu implisit INNER JOINdengan menambahkan sebuah kondisional.

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

Atau INNER JOINsintaksis eksplisit dan baru ,

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

Jadi, dalam contoh Anda ..

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

Ini pada dasarnya sama dengan sintaks yang lebih baru,

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

yang sebenarnya sama, dalam hal ini, karena to_tsquery()mengembalikan baris dan bukan set,

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;

Namun, hal di atas berpotensi menyebabkan to_tsquery('neutrino|(dark & matter)')terjadi dua kali, tetapi dalam kasus ini tidak - to_tsqueryditandai sebagai STABIL (diverifikasi dengan \dfS+ to_tsquery).

STABLEmenunjukkan bahwa fungsi tidak dapat memodifikasi database, dan bahwa dalam pemindaian tabel tunggal itu akan secara konsisten mengembalikan hasil yang sama untuk nilai argumen yang sama, tetapi hasilnya dapat berubah di seluruh pernyataan SQL. Ini adalah pilihan yang sesuai untuk fungsi yang hasilnya tergantung pada pencarian basis data, variabel parameter (seperti zona waktu saat ini), dll. (Ini tidak pantas untuk pemicu SETELAH yang ingin meminta baris yang dimodifikasi oleh perintah saat ini.) Juga perhatikan bahwa current_timestamp keluarga fungsi memenuhi syarat sebagai stabil, karena nilainya tidak berubah dalam suatu transaksi.

Untuk perbandingan yang lebih lengkap dari perbedaan antara SQL-89, dan SQL-92, lihat juga jawaban saya di sini

Evan Carroll
sumber
Terima kasih banyak. Saya baru mulai dengan SQL. Masuk akal untuk ,menjadi cross join karena itu hanya produk Cartesian dan tidak ada perbandingan yang terlibat. Bisakah Anda menjawab 1 pertanyaan lagi TOLONG? apa yang t(x)di (values(1)) AS t(x)???
andrerpena
@andrerpena diperbarui.
Evan Carroll
1
kamu yang terbaik. Penjelasan jernih. Terima kasih banyak.
andrerpena
Belum pernah mendengar istilah "DARI alias" untuk alias tabel . to_tsquery()mengembalikan nilai bukan baris . Dan hanya karena suatu fungsi didefinisikan STABLE, itu tidak berarti perencana permintaan akan menghindari evaluasi berulang. Itu bisa .
Erwin Brandstetter
12

Manual memiliki penjelasan terperinci untuk koma dalam FROMdaftar di bab Ekspresi Tabel :

The FROMKlausul berasal tabel dari satu atau lebih tabel lain yang diberikan dalam daftar tabel acuan dipisahkan koma.

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

Referensi tabel bisa berupa nama tabel (mungkin berkualitas skema), atau tabel turunan seperti subquery, JOINkonstruk, atau kombinasi kompleks dari semuanya. Jika lebih dari satu referensi tabel dicantumkan dalam FROMklausa, tabel tersebut disatukan silang (yaitu, produk Cartesian dari baris mereka terbentuk; lihat di bawah).

Fakta bahwa referensi tabel yang dipisahkan koma telah didefinisikan dalam versi standar SQL yang lebih lama daripada JOINsintaksis eksplisit tidak membuat koma salah atau ketinggalan zaman. Gunakan sintaks gabungan eksplisit, di mana secara teknis diperlukan (lihat di bawah) atau di mana itu membuat teks kueri lebih jelas.

Manual lagi:

FROM T1 CROSS JOIN T2setara dengan FROM T1 INNER JOIN T2 ON TRUE (lihat di bawah). Ini juga setara dengan FROM T1, T2.

Tetapi "setara" tidak berarti identik . Ada perbedaan yang halus, seperti catatan manual :

Catatan
Kesetaraan terakhir ini tidak berlaku tepat ketika lebih dari dua tabel muncul, karena JOINmengikat lebih erat daripada koma. Misalnya FROM T1 CROSS JOIN T2 INNER JOIN T3 ON conditiontidak sama dengan FROM T1, T2 INNER JOIN T3 ON conditionkarena conditionbisa referensi T1dalam kasus pertama tetapi bukan yang kedua.

Pertanyaan terkait ini menunjukkan relevansi perbedaan:

Pada dasarnya, pengamatan Anda benar:

menurut saya itu mendeklarasikan variabel yang disebut kueri sehingga dapat menggunakannya beberapa kali.

Fungsi apa pun dapat digunakan sebagai "fungsi tabel" dalam FROMdaftar. Dan parameter fungsi dapat merujuk kolom dari semua tabel ke kiri fungsi, karena notasi:

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

benar-benar setara dengan:

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

Manual tentang permintaan LATERAL:

Fungsi tabel yang muncul FROMjuga dapat didahului oleh kata kunci LATERAL, tetapi untuk fungsi kata kunci adalah opsional ; argumen fungsi dapat berisi referensi ke kolom yang disediakan oleh sebelumnya DARI item dalam hal apapun.

Penekanan berani saya.

Kata kunciAS tersebut benar-benar bunyi opsional sebelum alias tabel (sebagai lawan dari alias kolom , di mana disarankan untuk tidak menghilangkan ASuntuk menghindari kemungkinan ambiguitas). Jawaban terkait dengan lebih banyak:

Erwin Brandstetter
sumber