Sql 如果右侧包含特定的内容,如何从多到多不返回任何内容?
我有一个通过ORM映射的多对多。我从左表中选择,并使用2个左外部联接拉入右表 一切正常,但我有一个例子,如果正确的表包含一个特定的值,那么查询应该什么也不返回 下面是一个精心设计的简化示例:Sql 如果右侧包含特定的内容,如何从多到多不返回任何内容?,sql,postgresql,Sql,Postgresql,我有一个通过ORM映射的多对多。我从左表中选择,并使用2个左外部联接拉入右表 一切正常,但我有一个例子,如果正确的表包含一个特定的值,那么查询应该什么也不返回 下面是一个精心设计的简化示例: people people_fruits fruits id | name people_id | fruit_id id | name --------------------------------------------------- 1 | T
people people_fruits fruits
id | name people_id | fruit_id id | name
---------------------------------------------------
1 | Tom 1 | 1 1 | apple
2 | Paul 1 | 2 2 | banana
3 | Kim 2 | 1 3 | orange
2 | 3
给定的查询可能如下所示:
SELECT p.*, f.*
FROM people AS p
LEFT OUTER JOIN people_fruits AS pf ON pf.people_id = p.id
LEFT OUTER JOIN fruits AS f ON pf.fruits_id=f.id
WHERE p.id = 1;
相当标准。但假设我想假装与橘子有关的人根本不存在,对不起,橘子迷。我希望以下查询返回一个空集:
SELECT p.*, f.*
FROM people AS p
LEFT OUTER JOIN people_fruits AS pf ON pf.people_id = p.id
LEFT OUTER JOIN fruits AS f ON pf.fruits_id=f.id
WHERE p.id = 2;
此查询应返回一个空集
对Tom和Kim的查询应返回结果,但对Paul的查询不应返回结果
如何编写这样的查询?一种选择是按个人进行聚合,并声明他从未与橙子关联:
WITH cte AS (
SELECT p.id
FROM people AS p
LEFT JOIN people_fruits AS pf ON pf.people_id = p.id
LEFT JOIN fruits AS f ON pf.fruits_id = f.id
GROUP BY p.id
HAVING COUNT(*) FILTER (WHERE f.name = 'orange') = 0
)
SELECT p.*, f.*
FROM people AS p
LEFT JOIN people_fruits AS pf ON pf.people_id = p.id
LEFT JOIN fruits AS f ON pf.fruits_id = f.id
WHERE p.id IN (SELECT id FROM cte);
您可以使用“不存在”或“不存在”,如下所示。NOT IN必须小心使用,因为它需要同时处理null条件
-- NOT EXISTS --
SELECT p.*, f.*
FROM people AS p
LEFT JOIN people_fruits AS pf ON pf.people_id = p.id
LEFT JOIN fruits AS f ON pf.fruits_id = f.id
-- added this where condition with not exists
WHERE NOT EXISTS (SELECT 1
FROM people_fruits PFIN JOIN fruits FIN
ON PFIN.fruits_id = FIN.id
AND FIN.NAME = 'orange'
and PFIN.people_id = p.id);
-- NOT IN --
SELECT p.*, f.*
FROM people AS p
LEFT JOIN people_fruits AS pf ON pf.people_id = p.id
LEFT JOIN fruits AS f ON pf.fruits_id = f.id
-- added this where condition with not IN
WHERE p.id not in (SELECT PFIN.people_id
FROM people_fruits PFIN JOIN fruits FIN
ON PFIN.fruits_id = FIN.id
AND FIN.NAME = 'orange');
干杯 谢谢你的回答,很有效!我检查另一个答案是否正确,只是因为它比您提供的代码更适合ORM片段。干杯