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

kueri untuk satu set dalam database relasional

Saya tidak akan mengomentari apakah ada skema yang lebih cocok untuk melakukan ini (sangat mungkin), tetapi untuk skema yang memiliki kolom name dan item , kueri berikut akan berfungsi. (sintaks mysql)

SELECT k.name
FROM (SELECT DISTINCT name FROM sets) AS k
INNER JOIN sets i1 ON (k.name = i1.name AND i1.item = 1)
INNER JOIN sets i2 ON (k.name = i2.name AND i2.item = 3)
INNER JOIN sets i3 ON (k.name = i3.name AND i3.item = 5)
LEFT JOIN sets ix ON (k.name = ix.name AND ix.item NOT IN (1, 3, 5))
WHERE ix.name IS NULL;

Idenya adalah bahwa kita memiliki semua set kunci di k , yang kemudian kita gabungkan dengan set data item di sets sekali untuk setiap set item dalam set yang kita cari, tiga dalam kasus ini. Masing-masing dari tiga gabungan bagian dalam dengan alias tabel i1 , i2 dan i3 menyaring semua nama set yang tidak berisi item yang dicari dengan gabungan itu. Akhirnya, kami memiliki gabungan kiri dengan sets dengan tabel alias ix , yang membawa semua item tambahan di set, yaitu, setiap item yang tidak kami cari. ix.name adalah NULL jika tidak ada item tambahan yang ditemukan, persis seperti yang kita inginkan, maka WHERE ayat. Kueri mengembalikan baris yang berisi set kunci jika set ditemukan, sebaliknya tidak ada baris.

Sunting: Gagasan di balik jawaban collapsars tampaknya jauh lebih baik daripada milik saya, jadi inilah versi yang lebih pendek dengan penjelasannya.

SELECT sets.name
FROM sets
LEFT JOIN (
    SELECT DISTINCT name
    FROM sets
    WHERE item NOT IN (1, 3, 5)
) s1
ON (sets.name = s1.name)
WHERE s1.name IS NULL
GROUP BY sets.name
HAVING COUNT(sets.item) = 3;

Idenya di sini adalah subquery s1 memilih kunci dari semua set yang berisi item lain yang kita cari. Jadi, ketika kami pergi, gabungkan sets dengan s1 , s1.name adalah NULL ketika set hanya berisi item yang kita cari. Kami kemudian mengelompokkan berdasarkan set kunci dan menyaring setiap set yang memiliki jumlah item yang salah. Kami kemudian hanya memiliki set yang hanya berisi item yang kami cari dan dengan panjang yang benar. Karena set hanya dapat berisi satu item, hanya ada satu set yang memenuhi kriteria tersebut, dan itulah yang kami cari.

Sunting: Saya baru sadar bagaimana melakukan ini tanpa pengecualian.

SELECT totals.name
FROM (
    SELECT name, COUNT(*) count
    FROM sets
    GROUP BY name
) totals
INNER JOIN (
    SELECT name, COUNT(*) count
    FROM sets
    WHERE item IN (1, 3, 5)
    GROUP BY name
) matches
ON (totals.name = matches.name)
WHERE totals.count = 3 AND matches.count = 3;

Subquery pertama menemukan jumlah total item di setiap set dan yang kedua menemukan jumlah item yang cocok di setiap set. Saat matches.count adalah 3, set memiliki semua item yang kita cari, dan jika totals.count juga 3, set tidak memiliki item tambahan.



  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 - Hapus nilai default untuk bidang Datetime

  2. Apa arti parameter TINYINT (parameter)?

  3. Menghubungkan Satu tabel ke Banyak tabel

  4. Cara GABUNG tiga tabel di Codeigniter

  5. PHPExcel Render tag html di baris tabel mysql