这是一个名为fruits
的表:
id fruit_name quantity date
1 | 'apple' | 10 | '2019-01-01'
2 | 'peach' | 15 | '2019-01-02'
3 | 'plum' | 5 | '2019-01-05'
4 | 'banana' | 10 | '2019-01-06'
5 | 'orange' | 20 | '2019-01-06'
6 | 'grape' | 25 | '2019-01-09'
我正在尝试从两个子查询创建查询。仅当两个子查询均两者均返回任何结果时,主查询才应返回结果。因此,如果两个子查询中的任何一个都没有任何结果,那么整个查询将不返回任何内容。
以下是我正在处理的查询。它有点像我要创建的:
WITH r AS (
SELECT *
FROM fruits
WHERE fruit_name = ('pear')
)
SELECT *
FROM r
UNION ALL
SELECT *
FROM fruits
WHERE fruit_name = ('banana')
AND EXISTS (
SELECT *
FROM r
);
因此该查询将不返回任何结果,因为第一个子查询要求输入“ pear”,并且fruits
表中没有“ pear”。 按预期运行。
但是,如果在查询中交换“ pear”和“ banana”,那么它将返回一行:“ banana”行。这不是我想要的事情-在这种情况下,我也希望它不返回任何内容。
因此,基本上,如何修改此查询(或使用更好的查询),使其仅返回结果 ,如果两个子查询每个中的每一个都有结果?
答案 0 :(得分:2)
在where子句中使用两项检查:
select *
from fruits
where fruit_name in ('banana', 'pear')
and exists (
select from fruits
where fruit_name = 'banana')
and exists (
select from fruits
where fruit_name = 'pear');
请注意,在Postgres中,选择列表可能为空。您可以选择列或常量
...
and exists (
select id from fruits
where fruit_name = 'banana')
...
但这不会影响结果。
或者,您可以检查结果是否包含同时包含banana
和pear
的行:
with results as (
select *
from fruits
where fruit_name in ('banana', 'pear')
)
select *
from results
where (
select count(distinct fruit_name)
from results
) = 2
答案 1 :(得分:1)
您可以使用单个子查询来表达:
select f.*
from fruits f
where f.fruit_name in ('banana', 'pear') and
exists (select 1
from fruits f2
where f2.fruit_name in ('banana', 'pear') and
f2.fruit_name <> f.fruit_name
);
但是,假设名称是唯一的,我倾向于这样做:
select f.*
from (select f.*, count(*) over () as cnt
from fruits f
where f.fruit_name in ('banana', 'pear')
) f
where cnt = 2;
如果您确实有重复项,但是样本数据没有任何内容,则可以轻松调整此逻辑。
答案 2 :(得分:-1)
您可以使用两个子查询,而不是一个
WITH sub1 AS (
SELECT *
FROM fruits
WHERE fruit_name = ('pear')
),
sub2 AS (
SELECT *
FROM fruits
WHERE fruit_name = ('banana')
)
SELECT *
FROM sub1
UNION ALL
SELECT *
FROM sub2
WHERE
EXISTS (
SELECT *
FROM sub1
)
AND EXISTS (
SELECT *
FROM sub2
);