[英]MySQL conditional querying many to many relations (inner joined tables) from an array
我有一個colors
表和一個items
表,這兩個表之間存在多對多關系(通過items_colors
表)。 一個項目可以有多個 colors,一個顏色可以有多個項目。
items
id
colors
id
name
items_colors
item_id [foreign key: items(id)]
color_id [foreign key: colors(id)]
從 colors 的數組中,我想獲取所有僅匹配一個或多個提供的 colors 的項目。 如果某個項目還與數組中未指定的其他顏色相關聯,則不應檢索它。
SELECT
`*`
FROM
`items`
INNER JOIN `items_colors` ON `items_colors`.`item_id` = `items`.`id`
INNER JOIN `colors` ON `colors`.`id` = `items_colors`.`color_id`
WHERE
`colors`.`name` IN('green', 'blue')
在上面的示例中,我想獲取與給定數組匹配的所有項目,因此所有具有green或blue或綠色和藍色的項目。 但是,如果一個項目有藍色和紅色colors(或只有紅色,或沒有顏色),則應將其排除在結果之外。
目前,我沒有找到合適的方法來做到這一點。 上面示例中的查詢檢索的數據比我預期的要多。 謝謝你的幫助!
一種方法使用聚合:
SELECT i.*
FROM items i JOIN
items_colors ic
ON ic.item_id = i.id JOIn
colors c
ON c.id = ic.color_id
GROUP BY i.id
HAVING SUM( c.name NOT IN ('green', 'blue') ) = 0;
這不會返回 colors,但您可以使用GROUP_CONCAT(c.name)
返回那些。
您還可以更積極地表達HAVING
子句:
HAVING COUNT(*) = SUM( c.name IN ('green', 'blue') )
也就是說,使用NOT EXISTS
可能更有效:
select i.*
from items i
where not exists (select 1
from item_colors ic join
colors c
on ic.color_id = c.id
where ic.item_id = i.id and
c.name NOT IN ('green', 'blue')
);
如果您正在運行 MySQL 8.0,則可以使用 window 函數進行過濾:
SELECT *
FROM (
SELECT
i.*,
c.*,
ic.*,
SUM(c.name NOT IN ('green', 'blue')) OVER(PARTITION BY i.id) cnt
FROM items i
INNER JOIN items_colors ic ON ic.item_id = i.id
INNER JOIN colors c ON c.id = ic.color_id
) t
WHERE c.name IN ('green', 'blue') and cnt = 0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.