Mysql
 sql >> база данни >  >> RDS >> Mysql

заявка за набор в релационна база данни

Няма да коментирам дали има по-подходяща схема за това (възможно е), но за схема с колони name и item , следната заявка трябва да работи. (синтаксис на 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;

Идеята е, че имаме всички зададени ключове в k , които след това присъединяваме с данните от набора в sets веднъж за всеки комплект от комплекта, който търсим, в този случай три. Всяко от трите вътрешни свързвания с псевдоними на таблица i1 , i2 и i3 филтрирайте всички имена на набори, които не съдържат търсения елемент с това обединение. И накрая, имаме ляво присъединяване с sets с псевдоним на таблица ix , което въвежда всички допълнителни елементи в комплекта, тоест всеки артикул, който не сме търсили. ix.name е NULL в случай, че не бъдат намерени допълнителни елементи, което е точно това, което искаме, по този начин WHERE клауза. Заявката връща ред, съдържащ ключа set, ако наборът е намерен, в противен случай няма редове.

Редактиране: Идеята зад отговора на колапсите изглежда е много по-добра от моята, така че ето малко по-кратка версия на това с обяснение.

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;

Идеята тук е подзаявката s1 избира ключовете на всички набори, които съдържат елементи, различни от тези, които търсим. По този начин, когато напуснахме join sets с s1 , s1.name е NULL когато комплектът съдържа само елементи, които търсим. След това групираме по ключ за набор и филтрираме всички набори с грешен брой елементи. След това остават само набори, които съдържат само елементи, които търсим, и са с правилна дължина. Тъй като наборите могат да съдържат елемент само веднъж, може да има само един набор, отговарящ на тези критерии и това е този, който търсим.

Редактиране: Просто ми хрумна как да направя това без изключване.

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;

Първата подзаявка намира общия брой елементи във всеки набор, а втората открива броя на съответстващите елементи във всеки набор. Когато matches.count е 3, комплектът има всички елементи, които търсим, и ако totals.count също е 3, в комплекта няма допълнителни елементи.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. sudo yum инсталирайте конфликт на php55w-mysqlnd

  2. mysql JOIN, как се тълкува това?

  3. MySQL тригери и SUM()

  4. Автоматично подреждане на обект при вмъкване в MySQL JSON колона с knex

  5. MySQL PDO е подготвен по-бързо от заявката? Това показва този прост тест