繁体   English   中英

MySQL从多对多关系中过滤许多元素

[英]MySQL filter many elements from many-to-many relationship

我目前正在处理通过多对多关系链接的对象(这意味着可以将许多对象链接到...相同类型的对象不多,但类型可以变化的对象也很多)。

但是,对于这个问题,多对多就足够了。

因此,假设我有一个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将返回与WHERE子句匹配的所有ObjectA 至于关系条件,您必须计算匹配的行:

  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通过透视表。

一种解决方案是在Have子句中计算匹配条件。

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示例

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM