Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

MySQL:gabungkan banyak tabel dalam satu Pernyataan

Bagaimana cara mendapatkan semua turunan dari simpul pohon dengan kueri rekursif di MySql?

Ini benar-benar masalah bagi MySql, dan ini adalah poin kunci untuk pertanyaan ini, tetapi Anda masih memiliki beberapa pilihan.

Dengan asumsi Anda memiliki data sampel seperti itu, tidak sebanyak sampel Anda tetapi cukup untuk menunjukkan:

create table treeNode(
id int, parent_id  int,  name varchar(10), type varchar(10),level int);
insert into treeNode 
(id, parent_id, name, type, level) values 
( 1,  0,  'C1    ', 'CATEGORY', 1),
( 2,  1,  'C1.1  ', 'CATEGORY', 2),
( 3,  2,  'C1.1.1', 'CATEGORY', 3),
( 4,  1,  'C1.2  ', 'CATEGORY', 2),
( 5,  4,  'C1.2.1', 'CATEGORY', 3),
( 3,  8,  'G1.1.1',    'GROUP', 3),
( 4,  9,  'G1.2  ',    'GROUP', 2),
( 5,  4,  'G1.2.1',    'GROUP', 3),
( 8,  9,  'G1.1  ',    'GROUP', 2),
( 9,  0,  'G1    ',    'GROUP', 1);

Pilihan pertama:kode level

Seperti contoh data kolom nama pada tabel treeNode. (Saya tidak tahu bagaimana mengatakannya dalam bahasa Inggris, beri komentar saya tentang ungkapan yang benar dari level code .)

Untuk mendapatkan semua turunan C1 atau G1 bisa jadi sederhana seperti ini:

select * from treeNode where type = 'CATEGORY' and name like 'C1%' ;
select * from treeNode where type = 'GROUP' and name like 'G1%' ;

Saya sangat menyukai pendekatan ini, bahkan membutuhkan kami untuk membuat kode ini sebelum treeNode disimpan di application. Ini akan lebih efisien daripada kueri atau prosedur rekursif ketika kita memiliki sejumlah besar catatan. Saya pikir ini adalah pendekatan denormalisasi yang baik.

Dengan pendekatan ini, pernyataan Anda ingin dengan bergabung bisa jadi:

SELECT distinct p.* --if there is only one tree node for a product, distinct is not needed
FROM product p
JOIN product_type pt
     ON pt.id= p.parent_id -- to get product type of a product
JOIN linked_TreeNode LC
     ON LC.product_id= p.id -- to get tree_nodes related to a product
JOIN (select * from treeNode where type = 'CATEGORY' and name like 'C1%' ) C --may replace C1% to concat('$selected_cat_name','%')
     ON LC.treeNode_id = C.id
JOIN (select * from treeNode where type = 'GROUP' and name like 'G1%' ) G --may replace G1% to concat('$selected_group_name','%')
     ON LC.treeNode_id = G.id
WHERE pt.name = '$selected_type'  -- filter selected product type, assuming using product.name, if using product.parent_id, can save one join by pt like your original sql

Manis, bukan?

Pilihan kedua:nomor level

Tambahkan kolom level ke tabel treeNode, seperti yang ditunjukkan di DDL.

Nomor level jauh lebih mudah dipertahankan daripada kode level dalam aplikasi.

Dengan nomor level untuk mendapatkan semua keturunan C1 atau G1 butuh sedikit trik seperti ini :

SELECT id, parent_id, name, type, @pv:=concat(@pv,',',id) as link_ids 
  FROM (select * from treeNode where type = 'CATEGORY' order by level) as t
  JOIN (select @pv:='1')tmp
 WHERE find_in_set(parent_id,@pv)
    OR find_in_set(id,@pv);
 -- get all descendants of `C1`

SELECT id, parent_id, name, type, @pv:=concat(@pv,',',id) as link_ids 
  FROM (select * from treeNode where type = 'GROUP' order by level) as t
  JOIN (select @pv:=',9,')tmp
 WHERE find_in_set(parent_id,@pv)
    OR find_in_set(id,@pv) ;

Pendekatan ini lebih lambat dari yang pertama, tetapi masih lebih cepat daripada kueri rekursif.

sql lengkap untuk pertanyaan dihilangkan. Hanya perlu mengganti dua subquery C dan G dengan dua query di atas.

Catatan:

Ada banyak pendekatan serupa seperti di sini , di sini , atau bahkan di sini . Mereka tidak akan bekerja kecuali diperintahkan oleh nomor level atau kode level. Anda dapat menguji kueri terakhir di SqlFiddle ini dengan mengubah order by level untuk order by id untuk melihat perbedaannya.

Pilihan Lain:Model Kumpulan Bersarang

Silakan merujuk ke blog ini , saya belum tes. Tapi saya pikir ini mirip dengan dua pilihan terakhir.

Anda perlu menambahkan nomor kiri dan nomor kanan ke tabel treenode untuk menyertakan semua id keturunan di antara mereka.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana cara mengurutkan hasil kueri berdasarkan jarak dalam paket Laravel QueryBuilder / MySQL Spatial?

  2. Lakukan pilih dan beberapa sisipan sebagai transaksi menggunakan Konektor C?

  3. Cara bergabung memiliki banyak tabel relasi dan mengambil hasil berdasarkan jenis

  4. Panggilan Database Asinkron Node JS

  5. Muat konten ajax secara dinamis di fancybox dari database MySQL