MySQL 5.5
parent table: id | facts
child table: parent_id | foreign_key | facts
现在,我想找到父母,他们拥有一定数量的孩子,不多也不少。类似的东西:
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
但是这也将获得这组孩子的父记录:1,2,3,5,7,9。我只想要那些确切的孩子的父母:1,3,5,7,9。
有办法吗?
编辑: child.parent_id和child.fk 都不是唯一的。 child.fk是链接到另一个表的外键。 (“多对多关系”)所以父母很可能有孩子1,2,3,5,7,9。我完成此查询的全部理由是尽量避免为1,3,5,7,9创建新的父级,如果这样的父级已存在。
答案 0 :(得分:3)
假设child.id
对于每个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 :(得分:1)
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
答案 2 :(得分:1)
这个问题被称为(确切的)关系划分。本文中有许多有用的代码和解释: Divided We Stand: The SQL of Relational Division 。
解决问题的一种方法:
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) ;
另一个类似问题的链接,在StackOverflow,你可以找到10多个不同的解决方案(注意:它不是用于精确的除法,而是用于余数的划分)和性能测试(对于Postgres):<强> How to filter SQL results in a has-many-through relation 强>
答案 3 :(得分:1)
与eggyal的解决方案类似,但我只是想把它作为一种替代方案,因为它应该在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
是您想要匹配的IN子句中的子项的确切数量(在本例中为全部)
这将仅适用于不同的孩子,如果有重复,则会中断。