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

Masalah SQL:hubungan satu ke banyak dan model EAV

Jawaban singkat untuk pertanyaan Anda adalah tidak, tidak ada konstruksi sederhana di MySQL untuk mencapai set hasil yang Anda cari.

Tetapi dimungkinkan untuk dengan hati-hati (dengan susah payah) menyusun kueri semacam itu. Berikut ini contohnya, saya yakin Anda akan dapat menguraikannya. Pada dasarnya, saya menggunakan subkueri berkorelasi dalam daftar pilih, untuk setiap atribut yang ingin saya kembalikan.

SELECT t.id
     , t.name
     , t.nickname

     , ( SELECT v1.attribute_value 
           FROM team_information v1 
           JOIN attributes a1
             ON a1.id = v1.attribute_id AND a1.attribute_name = 'city'
          WHERE v1.team_id = t.id ORDER BY 1 LIMIT 1
       ) AS city

     , ( SELECT v2.attribute_value
           FROM team_information v2 JOIN attributes a2
             ON a2.id = v2.attribute_id AND a2.attribute_name = 'captain'
          WHERE v2.team_id = t.id ORDER BY 1 LIMIT 1
       ) AS captain

     , ( SELECT v3.attribute_value
           FROM team_information v3 JOIN attributes a3
             ON a3.id = v3.attribute_id AND a3.attribute_name = 'f_number'
          WHERE v3.team_id = t.id ORDER BY 1 LIMIT 1
       ) AS f_number

  FROM teams t
 ORDER BY t.id

Untuk atribut 'multi-nilai', Anda harus menarik setiap instance atribut secara terpisah. (Gunakan LIMIT untuk menentukan apakah Anda mengambil yang pertama, yang kedua, dll.)

     , ( SELECT v4.attribute_value
           FROM team_information v4 JOIN attributes a4
             ON a4.id = v4.attribute_id AND a4.attribute_name = 'nickname'
          WHERE v4.team_id = t.id ORDER BY 1 LIMIT 0,1
       ) AS nickname_1st

     , ( SELECT v5.attribute_value
           FROM team_information v5 JOIN attributes a5
             ON a5.id = v5.attribute_id AND a5.attribute_name = 'nickname'
          WHERE v5.team_id = t.id ORDER BY 1 LIMIT 1,1
       ) AS nickname_2nd

     , ( SELECT v6.attribute_value
           FROM team_information v6 JOIN attributes a6
             ON a6.id = v6.attribute_id AND a6.attribute_name = 'nickname'
          WHERE v6.team_id = t.id ORDER BY 1 LIMIT 2,1
       ) AS nickname_3rd

Saya menggunakan nama panggilan sebagai contoh di sini, karena klub sepak bola Amerika sering memiliki lebih dari satu nama panggilan, mis. Chicago Fire Soccer Club memiliki julukan:'The Fire', 'La Máquina Roja', 'Men in Red', 'CF97', dkk.)

BUKAN JAWABAN ATAS PERTANYAAN ANDA, TAPI ...

Sudahkah saya sebutkan berkali-kali sebelumnya, seberapa besar saya tidak suka bekerja dengan implementasi basis data EAV? Apa yang seharusnya menjadi kueri IMO yang sangat sederhana berubah menjadi hal yang terlalu rumit dari kueri yang berpotensi meredupkan cahaya.

Bukankah lebih mudah untuk membuat tabel di mana setiap "atribut" adalah kolom terpisah? Kemudian kueri untuk mengembalikan kumpulan hasil yang masuk akal akan terlihat lebih masuk akal...

SELECT id, name, nickname, city, captain, f_number, ... FROM team

Tapi apa yang benar-benar membuat saya bergidik adalah prospek bahwa beberapa pengembang akan memutuskan bahwa LDQ harus "disembunyikan" dalam database sebagai tampilan, untuk mengaktifkan kueri "lebih sederhana".

Jika Anda mengikuti rute ini, HARAP TOLONG TOLONG tahan keinginan apa pun yang mungkin Anda miliki untuk menyimpan kueri ini dalam database sebagai tampilan.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MYSQL:Cara mendefinisikan atau mendapatkan variabel string PANJANG

  2. Periksa versi mySQL di Mac 10.8.5

  3. Mysql Gabung DAN SUM

  4. Mesin penyimpanan untuk meja tidak mendukung perbaikan. InnoDB atau MyISAM?

  5. kueri mysql untuk mendapatkan ulang tahun selama 10 hari ke depan