sql >> Databáze >  >> RDS >> Mysql

dotaz na množinu v relační databázi

Nebudu komentovat, zda pro to existuje vhodnější schéma (je to docela možné), ale pro schéma se sloupci name a item , měl by fungovat následující dotaz. (syntaxe 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;

Myšlenka je taková, že máme všechny nastavené klíče v k , které pak spojíme s daty sady položek v sets jednou pro každou položku v sadě, kterou hledáme, v tomto případě tři. Každé ze tří vnitřních spojení s aliasy tabulky i1 , i2 a i3 odfiltrujte všechny názvy sad, které neobsahují položku hledanou pomocí tohoto spojení. Nakonec máme levé spojení s sets s aliasem tabulky ix , která přináší všechny položky navíc v sadě, tedy každou položku, kterou jsme nehledali. ix.name je NULL v případě, že nejsou nalezeny žádné položky navíc, což je přesně to, co chceme, tedy WHERE doložka. Dotaz vrátí řádek obsahující klíč set, pokud je sada nalezena, jinak žádné řádky.

Upravit: Myšlenka odpovědí collapsars se zdá být mnohem lepší než ta moje, takže zde je trochu kratší verze s vysvětlením.

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;

Myšlenka je taková, že poddotaz s1 vybere klíče všech sad, které obsahují jiné položky než ty, které hledáme. Když jsme tedy odešli, připojte se k sets s s1 , s1.name je NULL když sada obsahuje pouze položky, které hledáme. Potom seskupíme podle klíče sady a odfiltrujeme všechny sady, které mají nesprávný počet položek. Zbývají nám pak pouze sady, které obsahují pouze položky, které hledáme a mají správnou délku. Protože sady mohou obsahovat položku pouze jednou, může existovat pouze jedna sada splňující tato kritéria, a to je ta, kterou hledáme.

Upravit: Právě mi došlo, jak to udělat bez vyloučení.

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;

První dílčí dotaz zjišťuje celkový počet položek v každé sadě a druhý zjišťuje počet odpovídajících položek v každé sadě. Když matches.count je 3, sada obsahuje všechny položky, které hledáme, a pokud totals.count je také 3, sada neobsahuje žádné další položky.



  1. SQL:Získejte produkty z kategorie, ale také musí být v jiné sadě kategorií

  2. Zkontrolujte místo používané tabulkou na serveru SQL

  3. Vlastní formátovaný JSON z MYSQL PDO pro použití v NVD3.js

  4. Formát data MySQL DD/MM/RRRR vybrat dotaz?