使用连接条件排除结果

时间:2012-04-24 18:56:16

标签: sql relational-division

我正在尝试使用加入排除来生成sql请求。 说明:

表格元素

id # name #
 1  Sea
 2  tree

表格颜色

id # name #
 1    green
 2    blue
 3    brown

表关系

element_id # colour_id
     1           2
     2           1
     2           3

我有“获取其中一种颜色的元素”的工作请求。 例如绿色和蓝色:

SELECT element.name, colour.name FROM element
LEFT JOIN relation 
  ON (element.id = relation.element_id)
LEFT JOIN colour
  ON (colour.id = relation.colour_id)
WHERE (relation.colour_id = 1 OR relation.colour_id = 2)

我想请求“获取与所有列出的颜色有关系的元素”绿色棕色的位置返回

我试图将'OR'更改为'AND',但请求返回0结果:/

4 个答案:

答案 0 :(得分:2)

解决此问题的一般方法是过滤值并计算它们在结果中出现的次数。如果相等,则找到所有元素。

select element_id
from relation
where colour_id in (1, 2)
group by element_id
having count (distinct colour_id) = 2

拥有此表可以将其连接到原始表以生成完整列集:

SELECT element.name, colour.name 
  FROM relation 
  INNER JOIN
  (
    select element_id
      from relation
     where colour_id in (1, 2)
     group by element_id
    having count (distinct colour_id) = 2
  ) matches
    ON relation.element_id = matches.element_id
  INNER JOIN element
     ON element.id = relation.element_id
  INNER JOIN colour
     ON colour.id = relation.colour_id

答案 1 :(得分:0)

您的WHERE子句中有一个拼写错误 - 其中一个ID是2(“蓝色”)而不是3(“棕色”)。它应该是

WHERE (relation.colour_id = 1 OR relation.colour_id = 3)

(或缩写形式:

WHERE relation.colour_id IN (1, 3)

)。

但请注意,您当前的查询 - 虽然在此修复后它应该适用于您的示例数据 - 但通常不会给您正确的结果。它将为您提供与任何指定颜色相关联的元素。 @ Nikola的答案给出了正确的解决方案。

答案 2 :(得分:0)

这种类型的查询可以使用SQL的一些基于集合的运算符来处理:

哪些元素与所有颜色有关系?

使用ALL运算符(语法可能因数据库而略有不同):

SELECT element.name
FROM element
WHERE ( SELECT colour.id FROM relation 
      INNER JOIN colour ON colour.id = relation.colour_id
      WHERE relation.element_id = element.id )
= ALL ( SELECT colour.id from colour)
;

使用EXCEPT运算符:

SELECT element.name
FROM element
WHERE NOT EXISTS 
( SELECT colour.id from colour
   EXCEPT
  SELECT colour.id FROM relation 
  INNER JOIN colour ON colour.id = relation.colour_id
  WHERE relation.element_id = element.id 
)
;

答案 3 :(得分:0)

没有子选择,我建议:

SELECT
    e.id AS id
FROM
    element AS e
    LEFT OUTER JOIN relation AS r ON r.element_id = e.id
    GROUP BY e.id HAVING SUM(CASE WHEN r.colour_id = 1 THEN 1 ELSE 0 END ) = 0
ORDER BY e.id ASC;

之后,您可以按ID选择元素。