我目前正在处理通过多对多关系链接的对象(这意味着许多对象可以链接到...不是很多相同类型的对象,但许多类型的对象可能会有所不同)
但是,对于这个问题,多对多就足够了。
所以,假设我有一个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的问题以及他们如何过滤他们的标签。如果您选择了一堆标签,则只返回所有所选标签的问题,而不是所有至少一个的问题 label。
谢谢!
答案 0 :(得分:1)
从您的评论中听起来您不希望LEFT JOIN
返回与ObjectA
子句匹配的所有WHERE
。至于关系条件,你必须计算匹配的行:
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;
OR:
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
。
答案 1 :(得分:1)
解决方案是计算having子句中的匹配条件。
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
WHERE b.id IN (1, 2, 3) GROUP BY a.id HAVING COUNT(b.id)=3;
请参阅sqlfidle example。