如何在联接表中检查完全匹配

时间:2019-02-14 11:54:02

标签: sql db2

让我们考虑以下问题:

  • 带有ID,标题,大小的表格“图片”。
  • 带有ID,标签的表'Color'。
  • 具有picture_id,color_id的联接表“ Pic_Col”
  • 每张图片都有1到n种颜色

我正在尝试在SQL中找到(DB2,但我对其他RDBMS功能很好奇)一种返回可以回答以下问题的方法:

  • 一个查询:
      

    ID为X的图片仅包含蓝色和黄色吗?

  • 一个查询:

      

    ID为Y的图片至少包含蓝色和黄色吗?

         

    ID为Z的图​​片至少包含蓝色和黄色但没有红色吗?

我想提供以下参数:图片ID,所需颜色列表,不需要的颜色列表。

我设法找到的唯一解决方案基于具有子查询或X联接(X是查询中颜色的数量)和聚合(EXISTS等)的CASE WHEN ... < / p>

    SELECT 1
    FROM 
        picture p
    WHERE
        p.id = 123
        AND EXISTS (
            SELECT 1
            FROM pic_col pc
                INNER JOIN color c ON (c.id = pc.color_id AND c.label = 'blue')
            WHERE
                pc.picture_id = p.id
        )
        AND EXISTS (
            SELECT 1
            FROM pic_col pc
                INNER JOIN color c ON (c.id = pc.color_id AND c.label = 'yellow')
            WHERE
                pc.picture_id = p.id
        )
        AND NOT EXISTS (
            SELECT 1
            FROM pic_col pc
                INNER JOIN color c ON (c.id = pc.color_id AND c.label = 'red')
            WHERE
                pc.picture_id = p.id
        );

1 个答案:

答案 0 :(得分:1)

我喜欢为此目的进行条件聚合。

  

ID为X的图片仅包含蓝色和黄色吗?

select picture_id
from pic_col pc join
     colors c
     on pc.color_id = c.id
group by picture_id
having count(*) = sum(case when c.label in ('blue', 'yellow')
  

ID为Y的图片至少包含蓝色和黄色吗?

select picture_id
from pic_col pc join
     colors c
     on pc.color_id = c.id
group by picture_id
having sum(case when c.label = 'blue' then 1 else0 end) > 0 and
       sum(case when c.label = 'yellow' then 1 else 0 end) > 0;
  

ID为Z的图​​片至少包含蓝色和黄色但没有红色吗?

select picture_id
from pic_col pc join
     colors c
     on pc.color_id = c.id
group by picture_id
having sum(case when c.label = 'blue' then 1 else0 end) > 0 and
       sum(case when c.label = 'yellow' then 1 else 0 end) > 0 and
       sum(case when c.label = 'red' then 1 else 0 end) =  0;

having子句将每个图片的每种颜色(或一组颜色)的匹配数量相加。 > 0表示存在颜色。 = 0表示没有颜色。