Bagaimana untuk mencipta pertanyaan rekursif hierarki MySQL?
P粉329425839
P粉329425839 2023-08-23 21:55:29
0
1
486

我有一个 MySQL 表,如下所示:

id 名称 parent_id
19 类别1 0
20 类别2 19
21 类别3 20
22 类别4 21
... ... ...

现在,我想要一个 MySQL 查询,我只需向其提供 id [例如 id=19],我只需向其提供 id [例如 id=19],我只获子 id [即结果应该有 id ' 20,21,22']....

子级的层次结构未知;它可能会有所不同......

我知道如何使用 untuk 循环来做到这一点...但是如何使用单个 MySQL 查询来实现相同的目的?

P粉329425839
P粉329425839

membalas semua (1)
P粉393030917

UntukMySQL 8+:Gunakan sintaks rekursif使用.
UntukMySQL 5.x:Gunakan pembolehubah sebaris, ID laluan atau sambung sendiri.

MySQL 8+

with recursive cte (id, name, parent_id) as ( select id, name, parent_id from products where parent_id = 19 union all select p.id, p.name, p.parent_id from products p inner join cte on p.parent_id = cte.id ) select * from cte;

parent_id = 19中指定的值应设置为您要选择其所有后代的父级的id.

MySQL 5.x

Untuk versi MySQL (sehingga versi 5.7) yang tidak menyokong ungkapan jadual biasa, anda boleh menggunakan pertanyaan berikut untuk mencapai ini:

select id, name, parent_id from (select * from products order by parent_id, id) products_sorted, (select @pv := '19') initialisation where find_in_set(parent_id, @pv) and length(@pv := concat(@pv, ',', id))

Ini adalahfiddle.

Di sini,@pv := '19'中指定的值应设置为您要选择其所有后代的父级的id. p>

Ini juga akan berfungsi jika ibu bapa mempunyai ramai anak. Tetapi setiap rekod diperlukan untuk memenuhi syaratparent_id , jika tidak, hasilnya akan menjadi tidak lengkap.

Tugasan boleh ubah dalam pertanyaan

Pertanyaan ini menggunakan sintaks MySQL khusus: pembolehubah diperuntukkan dan diubah suai semasa pelaksanaan. Membuat beberapa andaian tentang susunan pelaksanaan:

  • Menilai dahulu di manafrom子句。这就是@pvdimulakan.
  • Ikuti daripadafrom别名检索的顺序对每条记录评估where子句。因此,这里设置的条件仅包括父级已被识别为位于后代树中的记录(主要父级的所有后代都将逐步添加到@pv).
  • Rentetanwhere子句中的条件按顺序求值,一旦总结果确定,求值就会中断。因此,第二个条件必须位于第二位,因为它将 id 添加到父列表中,并且只有在 id 通过第一个条件时才会发生这种情况。调用length函数只是为了确保此条件始终为真,即使pvini menghasilkan nilai palsu atas sebab tertentu.

Secara keseluruhan, seseorang mungkin mendapati andaian ini terlalu berisiko untuk dipercayai.DokumentasiAmaran:

Jadi, walaupun ia konsisten dengan pertanyaan di atas, susunan penilaian mungkin masih berubah, contohnya apabila anda menambah syarat atau menggunakan pertanyaan ini sebagai paparan atau subquery dalam pertanyaan yang lebih besar. Ini ialah "ciri"yang akan dialih keluar dalam versi MySQL masa hadapan 一>:

Seperti yang dinyatakan di atas, bermula dengan MySQL 8.0, anda harus menggunakan sintakswithrekursif.

kecekapan

Untuk set data yang sangat besar, penyelesaian ini mungkin lambat kerana operasifind_in_setbukanlah cara yang paling ideal untuk mencari nombor dalam senarai, dan pastinya bukan apabila ia datang untuk memadankan bilangan rekod yang dikembalikan.

Alternatif 1:使用递归连接

Semakin banyak pangkalan data melaksanakanSQL:1999 standard ISOWITH [RECURSIVE]递归查询的sintaks(cth.Postgres 8.4+,SQL Server 2005+ a>,DB2,, ra QLite 3.8.4+,Firebird 2.1 +,H2,HyperSQL 2.1.0+,Teradata,MariaDB 10.2.2+). Bermula denganversi 8.0, MySQL juga menyokongnya. Lihat bahagian atas jawapan ini untuk digunakan sintaks.

Pangkalan data

some mempunyai sintaks bukan standard alternatif untuk carian hierarki, sepertiCUBRIDdan pangkalan data lain.MySQL versi 5.7 tidak menyediakan fungsi sedemikian. Apabila enjin pangkalan data anda menyediakan sintaks ini atau anda boleh berhijrah ke enjin pangkalan data yang menyediakan sintaks ini, maka ini sudah pasti pilihan terbaik. Jika tidak, pertimbangkan alternatif berikut.Alternatif 2: Pengecam Gaya Laluan a>

Perkara menjadi lebih mudah jika anda memberikan nilai id yang mengandungi maklumat hierarki (laluan). Contohnya, dalam kes anda ini mungkin kelihatan seperti ini:

ID

Kemudian选择anda akan kelihatan seperti ini:

select id, name from products where id like '19/%'

Alternatif 3: Ulangi penyertaan diri

Jika anda mengetahui had atas kedalaman pokok hierarki, anda boleh menggunakan pertanyaansqlstandard seperti ini:

select p6.parent_id as parent6_id, p5.parent_id as parent5_id, p4.parent_id as parent4_id, p3.parent_id as parent3_id, p2.parent_id as parent2_id, p1.parent_id as parent_id, p1.id as product_id, p1.name from products p1 left join products p2 on p2.id = p1.parent_id left join products p3 on p3.id = p2.parent_id left join products p4 on p4.id = p3.parent_id left join products p5 on p5.id = p4.parent_id left join products p6 on p6.id = p5.parent_id where 19 in (p1.parent_id, p2.parent_id, p3.parent_id, p4.parent_id, p5.parent_id, p6.parent_id) order by 1, 2, 3, 4, 5, 6, 7;

Lihat iniViolin

whereSyarat menentukan keturunan ibu bapa yang ingin anda dapatkan. Anda boleh mengembangkan pertanyaan ini ke lebih banyak tahap mengikut keperluan.

Nama 19 Kategori 1 19/1 Kategori 2 19/1 Kategori 3 19/1/1/1 Kategori 4
    Muat turun terkini
    Lagi>
    kesan web
    Kod sumber laman web
    Bahan laman web
    Templat hujung hadapan
    Tentang kita Penafian Sitemap
    Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!