Jawaban dasar
Ada CTE (Ekspresi Tabel Umum) di Postgres (seperti di RDBMS modern utama apa pun kecuali MySQL). Sejak versi 9.1 yang menyertakan CTE pengubah data. Itu bisa "bersarang".
Update:MySQL 8.0 akhirnya menambahkan CTE.
Tidak seperti subkueri CTEs berpose sebagai hambatan optimasi. Perencana kueri tidak dapat memasukkan perintah sepele ke dalam perintah utama atau menyusun ulang gabungan di antara kueri utama dan CTE. Hal yang sama dimungkinkan dengan subquery. Mungkin (sangat) baik atau (sangat) buruk untuk kinerja, itu tergantung.
Bagaimanapun, CTE memerlukan sedikit lebih banyak overhead (biaya kinerja) daripada subquery.
Pembaruan:Postgres 12 akhirnya dapat membuat CTE biasa inline dalam kueri utama.
Detail yang tidak Anda minta
Pertanyaan Anda sangat mendasar, hal di atas mungkin sudah cukup untuk menjawabnya. Tapi saya akan menambahkan sedikit untuk pengguna tingkat lanjut (dan contoh kode untuk menunjukkan sintaks).
Semua CTE kueri didasarkan pada snapshot yang sama dari database. CTE berikutnya dapat menggunakan kembali output dari CTE sebelumnya (tabel sementara internal), tetapi efek pada tabel yang mendasarinya tidak terlihat untuk CTE lainnya. Urutan beberapa CTE adalah arbitrer kecuali sesuatu dikembalikan dengan RETURNING
klausa untuk INSERT
, UPDATE
, DELETE
- tidak relevan untuk SELECT
, karena tidak mengubah apa pun dan hanya membaca dari cuplikan.
Itu dapat memiliki efek halus dengan beberapa pembaruan yang akan memengaruhi baris yang sama. Hanya satu pembaruan dapat memengaruhi setiap baris. Manakah yang dipengaruhi oleh urutan CTE.
Coba prediksi hasilnya:
CREATE TEMP TABLE t (t_id int, txt text);
INSERT INTO t VALUES (1, 'foo'), (2, 'bar'), (3, 'baz');
WITH sel AS (SELECT * FROM t)
, up1 AS (UPDATE t SET txt = txt || '1' WHERE t_id = 1 RETURNING *)
, up2 AS (UPDATE t SET txt = t.txt || '2'
FROM up1
WHERE up1.t_id = t.t_id
RETURNING t.*)
, ins AS (INSERT INTO t VALUES (4, 'bamm'))
, up3 AS (UPDATE t SET txt = txt || '3' RETURNING *)
SELECT 'sel' AS source, * FROM sel
UNION ALL
SELECT 'up1' AS source, * FROM up1
UNION ALL
SELECT 'up2' AS source, * FROM up2
UNION ALL
SELECT 'up3' AS source, * FROM up3
UNION ALL
SELECT 't' AS source, * FROM t;
SQL Fiddle
Jangan kecewa, saya ragu ada banyak orang di sini yang bisa melakukannya. :)
Intinya:hindari perintah yang bertentangan di CTE.