Select 具有一组特定特征的行

Select the rows having a specific set of characteristics

对 hand-wavy 标题表示歉意,老实说,我无法在保持文本简短的同时想出更好的描述。这是完整的问题。

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

假设我有这样一个 table:

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');

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

所以如果我查询“绿色和红色”,我应该得到“草莓”。 但是,如果我查询“绿色和黄色”,我应该看到“香蕉”而不是“苹果”,因为后者还有一种颜色。

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

的可怕黑客
WITH cte AS (
  SELECT fruit FROM t WHERE color = 'green'
  INTERSECT SELECT fruit FROM t WHERE color = 'yellow')
SELECT fruit FROM cte;

这当然失败了,因为 returns 香蕉 苹果。

谁有更好的方案?

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[]))

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

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