带有AND规则的SQL过滤器跨越多行

时间:2017-06-13 17:00:08

标签: mysql sql sqlperformance

我有一个MySQL数据库,看起来像:

item table
| id | name |

item_category link table
| item_id | category_id |

category table
| id | name |

如果我想获取与许多类别中的一个相关的项目,我可以这样做:

SELECT item.*
FROM item
JOIN item_category ON item_category.item_id = item.id
LEFT JOIN category ON category.id = item_category.category_id
WHERE category.name in ("category_one", "category_two")

但是,如果我想获取与类别列表的 all 相关的项目,则问题会变得有点复杂,因为从我的查询返回的行每个都包含一个类别。如何编写仅包含与所有类别相关的项目的查询?

我尝试使用嵌套选择编写查询,如下所示:

SELECT item.*
FROM item
WHERE EXISTS (
  SELECT item.id
  FROM item_category ON item_category.item_id = item.id
  LEFT JOIN category ON category.id = item_category.category_id
  WHERE item_category.id = item.id
  AND category.name = "category_one"  
)
AND EXISTS (
  SELECT item.id
  FROM item_category ON item_category.item_id = item.id
  LEFT JOIN category ON category.id = item_category.category_id
  WHERE item_category.id = item.id
  AND category.name = "category_two"  
)

但即使在相关领域有索引,这也是令人难以置信的不可思议的。

感谢您就此问题提供任何意见。

2 个答案:

答案 0 :(得分:2)

执行此操作的典型方法是(1)加入"类别"为每个必须匹配的值连接一次,或者(2)汇总您的第一个查询(对项目进行分组)并过滤count(distinct category.name) =值列表中的项目数。

答案 1 :(得分:1)

考虑以下内容......

DROP TABLE IF EXISTS category;

CREATE TABLE category
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,name VARCHAR(12) NOT NULL UNIQUE
);

INSERT INTO category VALUES
(101,'animals'),
(102,'minerals'),
(103,'vegetables');

DROP TABLE IF EXISTS item_category;

CREATE TABLE item_category
(item_id INT NOT NULL
,category_id INT NOT NULL
,PRIMARY KEY(item_id,category_id)
);

INSERT INTO item_category VALUES
(1,101),
(1,102),
(1,103),
(2,102),
(3,101),
(3,103);

通过检查,我们可以看到只有第1项与所有类别相关联。

那么,我们如何选择那些不是<?p>的项目呢?

SELECT DISTINCT ic.item_id 
           FROM item_category ic 
           JOIN category c ON c.id <> ic.category_id 
           LEFT 
           JOIN item_category x 
             ON x.item_id = ic.item_id 
            AND x.category_id = c.id 
          WHERE x.item_id IS NULL;
+---------+
| item_id |
+---------+
|       2 |
|       3 |
+---------+

与所有类别相关的项目列表与此集合相反。