Pertanyaan diajukan
Anda tidak bisa referensikan alias tabel dari satu subkueri di kueri lain pada level yang sama (atau di bagian lain dari UNION
pertanyaan). Alias tabel hanya terlihat dalam kueri itu sendiri dan subkuerinya.
Anda bisa referensi kolom keluaran subkueri pada tingkat kueri yang sama dengan LATERAL JOIN
. Contoh:
Temukan elemen paling umum dalam larik dengan grup menurut
Solusi untuk jumlah level maksimum yang kecil
Hanya untuk beberapa level (jika Anda tahu maksimum), Anda dapat menggunakan kueri sederhana:
LEFT JOIN
ke n-1 instance dari tabel itu sendiri- Gunakan
COALESCE
danCASE
pernyataan untuk menentukan akar dan tinggi,
SELECT p1.c AS child, COALESCE(p3.p, p2.p, p1.p) AS parent
,CASE
WHEN p3.p IS NOT NULL THEN 3
WHEN p2.p IS NOT NULL THEN 2
ELSE 1
END AS height
FROM parent p1
LEFT JOIN parent p2 ON p2.c = p1.p
LEFT JOIN parent p3 ON p3.c = p2.p
WHERE p1.c IN (3, 8)
ORDER BY p1.c;
Ini adalah SQL standar dan harus bekerja di semua 4 RDBMS Anda menandai.
Solusi umum untuk jumlah level yang berubah-ubah
Gunakan CTE rekursif seperti @Ken sudah disarankan.
- Di kaki rekursif pertahankan anak untuk setiap baris, hanya memajukan induknya.
- Di bagian luar
SELECT
, hanya simpan baris denganheight
terbesar per anak.
WITH RECURSIVE cte AS (
SELECT c AS child, p AS parent, 1 AS height
FROM parent
WHERE c IN (3, 8)
UNION ALL
SELECT c.child, p.p AS parent, c.height + 1
FROM cte c
JOIN parent p ON p.c = c.parent
-- WHERE c.height < 10 -- to safeguard against endless loops if necessary
)
SELECT DISTINCT ON (child) *
FROM cte
ORDER BY child, height DESC;
DISTINCT ON
khusus untuk Postgres . Penjelasan:
Pilih baris pertama di setiap grup GROUP BY?
Sisanya akan bekerja dengan cara yang sama di Oracle dan bahkan SQLite , tetapi tidak di MySQL yang tidak mendukung CTE.
SQL Fiddle mendemonstrasikan keduanya.