联接到多个类别的项的 SQL 查询

SQL query for items joined to multiple categories

提问人:scms 提问时间:7/13/2023 最后编辑:forpasscms 更新时间:7/14/2023 访问量:55

问:

我有这 2 个表、内容项和一个类别的联接表。我只需要一个查询来选择多个类别中的项目(在所有类别中,而不是在任何类别中)。

-- content items
CREATE TABLE `items` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  [...]
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- a join table to a categories table
CREATE TABLE `item_categories` (
  `item_id` bigint(20) DEFAULT NULL,
  `category_id` bigint(20) DEFAULT NULL,
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

下面是一个查询,用于在连接表中选择两个类别中的条目:

SELECT `item_categories`.* FROM `item_categories`
  WHERE `item_categories`.`category_id` IN (11811, 11911)

现在将其与项目表连接起来,可以让我获得任何类别中的项目。简单:

SELECT DISTINCT `items`.* FROM `items`
  INNER JOIN `item_categories` ON `item_categories`.`item_id` = `items`.`id`
  WHERE `item_categories`.`category_id` IN (11811, 11911)

这有点傻,是的,但是尝试使用 AND(每次 0 个结果):

SELECT DISTINCT `items`.* FROM `items`
  INNER JOIN `item_categories` ON `item_categories`.`item_id` = `items`.`id`
  WHERE `item_categories`.`category_id` = 11811
    AND `item_categories`.`category_id` = 11911

这是我最接近的一次。这似乎过于复杂,一种手动连接,每个类别都有一个:WHERE ID IN

SELECT DISTINCT `items`.* FROM `items`
  WHERE ID IN (
    SELECT `item_categories`.item_id FROM `item_categories`
      WHERE `item_categories`.`category_id` = 11811
  )
  AND ID IN (
    SELECT `item_categories`.item_id FROM `item_categories`
      WHERE `item_categories`.`category_id` = 11911
  )

有没有更好(更简单)的方法来实现这一目标?

我认为必须有一种方法可以在自加入或分组的联接上设置条件,以便在所有类别中仅选择item_categories。

sql MySQL的 分组依据 拥有 sql-in

评论


答:

-1赞 forpas 7/13/2023 #1

使用 aggregation in 获取属于所有类别的 s:item_categoriesitem_id

SELECT *
FROM items
WHERE id IN (
  SELECT item_id 
  FROM item_categories
  WHERE category_id IN (11811, 11911)
  GROUP BY item_id
  HAVING COUNT(DISTINCT category_id) = 2 -- the number of categories
);

我在定义中没有看到 和 组合的任何唯一约束。
如果有,您可以从该条款中删除。
item_categoriesitem_idcategory_idDISTINCTHAVING