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

Model hierarki mana yang harus saya gunakan? Adjacency, Nested, atau Enumerated?

Biasanya, ada tiga jenis kueri dalam hierarki yang menyebabkan masalah:

  1. Kembalikan semua leluhur
  2. Kembalikan semua keturunan
  3. Kembalikan semua anak (keturunan langsung).

Berikut adalah tabel kecil yang menunjukkan kinerja berbagai metode di MySQL :

                        Ancestors  Descendants  Children        Maintainability InnoDB
Adjacency list          Good       Decent       Excellent       Easy            Yes
Nested sets (classic)   Poor       Excellent    Poor/Excellent  Very hard       Yes
Nested sets (spatial)   Excellent  Very good    Poor/Excellent  Very hard       No
Materialized path       Excellent  Very good    Poor/Excellent  Hard            Yes

Di children , poor/excellent berarti jawabannya tergantung pada apakah Anda mencampur metode dengan daftar adjacency, i. e. menyimpan parentID di setiap catatan.

Untuk tugas Anda, Anda memerlukan ketiga kueri:

  1. Semua leluhur untuk menunjukkan hal Bumi / Inggris / Devon
  2. Semua anak untuk menunjukkan "Tujuan di Eropa" (item)
  3. Semua turunan untuk menampilkan "Tujuan di Eropa" (hitungan)

Saya akan memilih jalan yang terwujud, karena hierarki semacam ini jarang berubah (hanya dalam kasus perang, pemberontakan, dll).

Buat kolom varchar bernama path , indeks dan isi dengan nilai seperti ini:

1:234:6345:45454:

di mana angka-angka tersebut adalah kunci utama dari orang tua yang sesuai, dalam urutan yang benar (1 untuk Eropa, 234 untuk Inggris, dll.)

Anda juga memerlukan tabel bernama levels untuk menjaga nomor dari 1 ke 20 (atau level sarang maksimum apa pun yang Anda inginkan).

Untuk memilih semua leluhur:

SELECT   pa.*
FROM     places p
JOIN     levels l
ON       SUBSTRING_INDEX(p.path, ':', l.level) <> p.path
JOIN     places pa
ON       pa.path = CONCAT(SUBSTRING_INDEX(p.path, ':', l.level), ':') 
WHERE    p.id = @id_of_place_in_devon

Untuk memilih semua anak dan jumlah tempat di dalamnya:

SELECT  pc.*, COUNT(pp.id)
FROM    places p
JOIN    places pc
ON      pc.parentId = p.id
JOIN    places pp
ON      pp.path BETWEEN pc.path AND CONCAT(pc.path, ':')
        AND pp.id NOT IN
        (
        SELECT  parentId
        FROM    places
        )
WHERE   p.id = @id_of_europe
GROUP BY
        pc.id


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Pemecahan Masalah Replikasi MySQL:Bagian Satu

  2. cara mengatasi ERROR 1045 (28000):Akses ditolak untuk pengguna 'ODBC'@'localhost' (menggunakan kata sandi:TIDAK) secara permanen

  3. cara menghapus catatan dari database dengan Ajax

  4. java.net.SocketException:Pipa rusak

  5. this._callback.apply bukan fungsi ! Node js kesalahan Mysql