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

Bagaimana mengembalikan hasil yang ditetapkan berdasarkan baris lain

Berikut adalah dua solusi berbeda:(Catatan:Saya menyebut bidang enum "package_type")

Solusi pertama (melalui fungsi IF()):

select 
  i.location, 
  if(ps.id is not null, ps.id, pg.id) as package_id
from 
  (select distinct location from Items) i
  inner join 
    (select i.location, p.id
     from Items i
       inner join Packages p on (i.package_id = p.id and p.package_type = 'general')
    ) pg on (i.location = pg.location)
  left join 
    (select i.location, p.id
     from Items i
       inner join Packages p on (i.package_id = p.id and p.package_type = 'special')
    ) ps on (i.location = ps.location)

Solusi ini pada dasarnya mengambil lokasi dan menggabungkannya ke paket dengan general (yang dianggap ada; karenanya inner join ) dan paket khusus (yang opsional; karenanya left join ). Itu membuat catatan seperti ini:

location | general-package | [special-package]

Kemudian menggunakan MySQL IF berfungsi untuk mencoba memilih ID paket khusus terlebih dahulu, lalu kembali ke ID paket umum.

Solusi ke-2 (melalui casting enum ke integer):

select i.location, p.id
from
  (select i.location, max(cast(package_type as unsigned)) as package_type
   from Items i
     left join Packages p on (i.package_id = p.id)
   group by location
  ) i
  inner join 
    (select i.location, p.id, p.package_type
     from Items i
       inner join Packages p on (i.package_id = p.id)
    ) p on (i.location = p.location and i.package_type = p.package_type)

Solusi ini mengeksploitasi fakta bahwa enum disimpan sebagai bilangan bulat. Itu melemparkan enum ke bilangan bulat. special dalam hal ini akan mengembalikan 2 dan general akan mengembalikan 1 . Karena khusus ini dijamin lebih tinggi dari umum dalam hal ini (yaitu 2> 1), kita dapat menggunakan MAX fungsi agregat. Sekarang kami pada dasarnya memiliki tabel lokasi dan "paket yang direkomendasikan" mereka (yaitu khusus jika ada, umum sebaliknya). Kami cukup menggabungkan ini ke kueri normal bersama dengan jenis paket yang diharapkan, dan itu mengembalikan hasil yang benar.

Penafian:Saya tidak yakin tentang efisiensi salah satu metode ini, jadi Anda mungkin ingin mengujinya sendiri.

Jika Anda ingin mendesain ulang tabel atau mendenormalkannya untuk efisiensi, saya pikir desain ini mungkin lebih cocok:

GeneralPackages table
id, name
1, General Package 1

SpecialPackages table
id, name
1, Special Package 1
2, Special Package 2

Items table
id, general_package_id, special_package_id, location
1, 1, NULL, America
2, 1, 2, Europe

Keuntungannya adalah lebih mudah untuk menerapkan beberapa aturan di tingkat basis data:

  • Lokasi harus selalu memiliki paket umum (Items.general_package_id dapat didefinisikan sebagai NOT NULL)
  • Lokasi hanya boleh memiliki satu paket umum (menambahkannya di bidang daripada gabungan menjamin bahwa hanya ada satu yang ditentukan)
  • Sebuah lokasi mungkin memiliki paling banyak satu paket khusus (menambahkannya di bidang daripada gabungan menjamin bahwa hanya ada satu yang ditentukan)
  • Kunci asing pada Items.general_package_id =GeneralPackages.id akan menjamin bahwa kolom tersebut hanya berisi paket valid yang bersifat "umum".
  • Hal yang sama dapat dilakukan untuk special_package_id.

Kerugiannya adalah Anda mungkin perlu menggunakan UNION ALL setiap kali Anda menggunakan salah satu kueri lama Anda.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. pesanan mysql dengan serikat sepertinya tidak berfungsi

  2. Bagaimana cara mengakses database mysql online di android?

  3. Kueri dieksekusi dua kali (karena kesalahan) di Jawa dengan nilai yang tidak diinginkan

  4. Masukkan hasil kueri Mysql ke dalam array di dalam kelas

  5. Nilai datetime salah Database Error Number:1292