我正在尝试使用加入排除来生成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结果:/
答案 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选择元素。