选择具有一组特定特征的行

时间:2021-01-15 11:35:51

标签: postgresql intersect

抱歉手卷标题,老实说,我无法在保持文本简短的同时提出更好的描述。这是完整的问题。

在包含两列的表中,我想选择第一列中的 one 条目,该条目具有我在第二列中指定的all 值。用一个玩具示例 (also on SQL Fiddle) 可以更好地解释这一点。

假设我有一张这样的表:

CREATE TABLE t (fruit TEXT, color TEXT);

INSERT INTO t (fruit, color) VALUES
('banana', 'green'),
('banana', 'yellow'),
('apple', 'green'),
('apple', 'red'),
('apple', 'yellow'),
('strawberry', 'green'),
('strawberry', 'red');

给定多种颜色,我需要检索具有所有这些颜色的水果(您可以假设只有一个)——不多也不少。

所以如果我查询“绿色和红色”,我应该得到“草莓”。 但是,如果我查询“green and yellow”,我应该看到“banana”而不是“apple”,因为后者还有一种额外的颜色。

到目前为止,我想出的是一个使用 INTERSECT 的可怕黑客:

WITH cte AS (
  SELECT fruit FROM t WHERE color = 'green'
  INTERSECT SELECT fruit FROM t WHERE color = 'yellow')
SELECT fruit FROM cte;

当然失败,因为返回香蕉苹果。

有人有更好的计划吗?

2 个答案:

答案 0 :(得分:2)

您可以为此使用布尔聚合:

select fruit
from the_table
group by fruit
having bool_and(color in ('green', 'yellow'));

如果你想用 INTERSECT 来做,你可以使用这样的东西:

-- all fruits that have at least those two colors 
select fruit
from t
where color in ('green', 'yellow')
group by fruit
having count (distinct color) = 2
intersect 
-- all fruits that have exactly two colors 
select fruit
from t
group by fruit
having count(distinct color) = 2

答案 1 :(得分:1)

demo:db<>fiddle

您可以聚合颜色并检查聚合数组是否等于具有您预期颜色的数组。

SELECT
    fruit
FROM t
GROUP BY fruit
HAVING ARRAY_AGG(color ORDER BY color) = '{green, yellow}'

demos:db<>fiddle

要获得独立于订单的解决方案,您可以例如:

SELECT
    fruit
FROM t
GROUP BY fruit
HAVING ARRAY_AGG(color) @> '{yellow, green}'
   AND ARRAY_AGG(color) <@ '{yellow, green}'

SELECT
    fruit
FROM t
GROUP BY fruit
HAVING ARRAY_AGG(color ORDER BY color) = 
   (SELECT ARRAY_AGG(unnest ORDER BY unnest) FROM unnest('{yellow, green}'::text[]))
相关问题