Sql 排除具有联接条件的结果

Sql 排除具有联接条件的结果,sql,relational-division,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,

我正在尝试使用联接排除发出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个结果:/

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

WHERE (relation.colour_id = 1 OR relation.colour_id = 3)
(或简称:

WHERE relation.colour_id IN (1, 3)
)


但是请注意,您当前的查询(尽管经过此修复后,它应该可以用于示例数据)通常不会给出正确的结果。它将为您提供与任何指定颜色关联的元素。@Nikola的答案给出了正确的解决方法。

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

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

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

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

使用ALL运算符(语法可能因数据库而异):

使用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 
)
;

如果没有子选择,我建议:

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选择元素。

不确定这是否是问题所在,但您在颜色id的末尾遗漏了一个“r”。否则看起来可以。您是希望在运行时将颜色作为参数传递进来,还是只希望在Where子句中显式指定它们?谢谢。我已经进行了调整:在我的主查询的(ids)中使用“select…having count…”和where element.id检索元素\u id。
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;