簡體   English   中英

MySQL 有條件地從數組中查詢多對多關系(內部連接表)

[英]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')

在上面的示例中,我想獲取與給定數組匹配的所有項目,因此所有具有greenblue綠色藍色的項目。 但是,如果一個項目有藍色紅色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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM