我目前正在研究通过多到任意关系链接的对象(这意味着许多对象可以链接到。。。同一类型的对象不多,但类型可能不同的对象很多)。
但是,对于这个问题,多对多就足够了。
所以,假设我有一个ObjectA表,它包含以下内容:
CREATE TABLE (
id INT(11) NOT NULL,
label VARCHAR(30) NOT NULL,
-- primary keys and all the stuff
);
CREATE TABLE ObjectB (
id INT(11) NOT NULL,
label VARCHAR(30) NOT NULL,
-- primary keys and all the stuff
);
CREATE TABLE ObjectA_ObjectB (
objectA_id INT(11) NOT NULL,
objectA_type VARCHAR(250) NOT NULL, -- for the many to any
objectB_id INT(11) NOT NULL,
-- primary keys and all the stuff
);
假设我想用ObjectB中的2或3个元素过滤ObjectA。你会认为我应该使用
IN
:SELECT *
FROM ObjectA a
LEFT JOIN ObjectA_ObjectB relation ON a.id = relation.objectA_id AND "ObjectA" = relation.objectA_class
LEFT JOIN ObjectB b ON relation.objectB_id = b.id
WHERE b.id IN (1, 2, 3);
但是,问题是,通过这个请求,它获取所有与至少一个搜索到的objectb(这里是1、2和3)链接的objectAs。但是,我想要的是那些有ObjectB的1,2和3的。
我已经尝试了一些东西(比如
ALL
可能性,或者考虑在SQL之外创建第一个过滤器),但是没有给出预期的结果。有什么想法吗?
总之,我希望能够做一点类似于GitHub的问题,以及他们如何过滤标签。如果选取一组标签,则只返回具有所有选定标签的问题,而不返回具有至少一个标签的所有问题。
谢谢!
最佳答案
从您的评论中,听起来您不希望LEFT JOIN
返回与ObjectA
子句匹配的所有WHERE
s。至于关系条件,您必须计算匹配的行:
SELECT *
FROM ObjectA a
JOIN ObjectA_ObjectB relation
ON a.id = relation.objectA_id
AND "ObjectA" = relation.objectA_class
JOIN ObjectB b
ON relation.objectB_id = b.id
GROUP BY a.id
HAVING COUNT(CASE WHEN b.id IN (1,2,3) THEN 1 ELSE NULL END)=3;
或:
SELECT *
FROM ObjectA a
JOIN ObjectA_ObjectB relation
ON a.id = relation.objectA_id
AND "ObjectA" = relation.objectA_class
JOIN ObjectB b
ON relation.objectB_id = b.id
AND b.id IN (1,2,3)
GROUP BY a.id
HAVING COUNT(*)=3;
如果在此查询中实际上不需要ObjectB数据,则可以进一步简化此操作:
SELECT a.*
FROM ObjectA a
JOIN ObjectA_ObjectB relation
ON a.id = relation.objectA_id
AND "ObjectA" = relation.objectA_class
AND relation.objectB_id IN (1,2,3)
GROUP BY a.id
HAVING COUNT(*)=3;
这假设每个
ObjectB.id
只能有一个通过透视表链接到ObjectA
。关于mysql - MySQL从多对多关系中过滤许多元素,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25015710/