/ / MySQL ako nájsť rodiča s presnou sadou detí? - mysql, sql

MySQL ako nájsť rodiča s presným súborom detí? - mysql, sql

MySQL 5.5

rodičovská tabuľka: id | fakty
detský stôl: parent_id | zahraničný_kľúč | fakty

Teraz by som chcel nájsť rodičov, ktorí majú určitý presný súbor detí, nie viac, nič menej. Niečo ako:

SELECT t1.`id`
from `parent_table` t1
LEFT JOIN `child_table` t2 ON t1.id=t2.parent_id
WHERE t2.`fk` = 1
AND t2.`fk` = 3
AND t2.`fk` = 5
AND t2.`fk` = 7
AND t2.`fk` = 9

Týmto však tiež získate rodičovský rekord s touto sadou detí: 1,2,3,5,7,9. A chcem iba tých rodičov, ktorí majú presná sada detí: 1,3,5,7,9.

Existuje spôsob?

ÚPRAVA: child.parent_id a child.fk sú obe nie sú jedinečné. dieťa.fk je cudzí kľúč spájajúci s inou tabuľkou. (Vzťah „medzi mnohými“). Je teda celkom možné, že rodič má deti 1,2,3,5,7,9. Celý môj dôvod na vykonanie tohto dotazu je pokúsiť sa vyhnúť vytvoreniu nového rodiča pre 1,3,5,7,9, ak taký rodič už existuje.

odpovede:

2 pre odpoveď č. 1

Za predpokladu, že child.id je jedinečný pre každého child.parent_id.

SELECT  a.id, a.facts
FROM    parent a
INNER JOIN child b
ON a.id = b.parent_ID
WHERE   b.id IN (1,3,5,7,9) AND        -- <<== list all ChildID here
EXISTS                         -- <<== this part checks if the parent_ID
(                              --           present on the EXISTS clause
SELECT  parent_ID          --           which only filters parents
FROM    child c            --           with 5 children
WHERE   b.parent_ID = c.parent_ID
GROUP   BY parent_ID
HAVING  COUNT(*) = 5       -- <<== total number of children
)
GROUP   BY a.id, a.facts
HAVING  COUNT(*) = 5                   -- <<== total number of children

1 pre odpoveď č. 2

Tento problém sa nazýva (presné) relačné delenie. V tomto článku nájdete množstvo užitočných kódov a vysvetlení: Divided We Stand: The SQL of Relational Division.

Jeden spôsob, ako to vyriešiť:

SELECT p.id AS parent_id
FROM parent AS p
WHERE EXISTS
( SELECT * FROM child AS c
WHERE c.fk = 1 AND c.parent_id = p.id)
AND EXISTS
( SELECT * FROM child AS c
WHERE c.fk = 3 AND c.parent_id = p.id)
AND EXISTS
( SELECT * FROM child AS c
WHERE c.fk = 5 AND c.parent_id = p.id)
AND EXISTS
( SELECT * FROM child AS c
WHERE c.fk = 7 AND c.parent_id = p.id)
AND EXISTS
( SELECT * FROM child AS c
WHERE c.fk = 9 AND c.parent_id = p.id)
AND NOT EXISTS
( SELECT * FROM child AS c
WHERE c.fk NOT IN (1,3,5,7,9) AND c.parent_id = p.id) ;

A ďalší odkaz na podobnú otázku, tu naStackOverflow, kde nájdete viac ako 10 rôznych riešení (poznámka: nejde o presné rozdelenie, ale o rozdelenie so zvyškom) a výkonnostné testy (pre Postgres): Ako filtrovať výsledky SQL vo vzťahu typu has-many-through


1 pre odpoveď č. 3
SELECT   parent_id
FROM     child_table
GROUP BY parent_id
HAVING   SUM(id IN (1,3,5,7,9)) = COUNT(*)
AND COUNT(DISTINCT id) = 5

1 pre odpoveď č. 4

Podobné ako riešenie Eggyal, ale myslel som si, že ho vhodím ako alternatívu, pretože by malo byť prenosnejšie cez RDBMS;

SELECT c.parent_id
FROM child_table c
GROUP BY c.parent_id
HAVING SUM(CASE WHEN c.id IN (1,3,5,7,9) THEN 1 ELSE -1 END) = 5

5 je presný počet detí v klauzule IN, ktoré chcete zhodovať (v tomto prípade všetky)

Toto bude pracujte iba s odlišnými deťmi, ak existujú duplikáty, rozbije sa.

SQLfiddle na testovanie s.