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 香蕉 和 苹果。
谁有更好的方案?
您可以聚合颜色并检查聚合数组是否等于具有您预期颜色的数组。
SELECT
fruit
FROM t
GROUP BY fruit
HAVING ARRAY_AGG(color ORDER BY color) = '{green, yellow}'
要获得独立于订单的解决方案,您可以例如:
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
对 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 香蕉 和 苹果。
谁有更好的方案?
您可以聚合颜色并检查聚合数组是否等于具有您预期颜色的数组。
SELECT
fruit
FROM t
GROUP BY fruit
HAVING ARRAY_AGG(color ORDER BY color) = '{green, yellow}'
要获得独立于订单的解决方案,您可以例如:
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