return 列数据未在 SQL HAVING 查询中使用
return column data not used in SQL HAVING query
我认为这应该很简单,但我不知所措。我想在 SQL 语句 HAVING 子句中未使用的列中 return 数据,而不必执行第二次查询。我正在使用 PostgreSQL,但这应该是一个相当普遍的问题。这是数据:
CREATE TABLE sandbox (
ret_val character(10),
key1 character(10),
key2 character(10),
value1 real,
value2 real
);
COPY sandbox (ret_val, key1, key2, value1, value2) FROM stdin;
baa DEF Book 0.800000012 0.270000011
oink GHI Play 0.200000003 0.280000001
Oink DEF Book 0.300000012 0.109999999
chirp GHI Play 0.100000001 0
woof DEF Play 0.400000006 0.300000012
meow DEF Play 0.699999988 0.219999999
woof ABC Book 0.140000001 0.939999998
baa ABC Play 0.25999999 0.75
meow ABC Play 0.75999999 0.150000006
neigh DEF Movie 0.970000029 0.349999994
cluck DEF Movie 0.870000005 0.550000012
quack GHI Movie 0.870000005 0.119999997
\.
我想 return (ret_val, value1, value2) 中的值仅用于 (key1,key2) 对唯一的情况。所以首先我使用 HAVING:
做一个 SELECT
=> SELECT key1,key2 from sandbox group by 1,2 HAVING count(*)=1;
key1 | key2
------------+------------
GHI | Movie
ABC | Book
(2 rows)
看到有两个独特的行。然后我 select 使用 HAVING 的输出我需要的数据:
=> SELECT ret_val,value1,value2 from sandbox where
(key1='ABC' and key2='Book') OR (key1='GHI' and key2='Movie');
ret_val | value1 | value2
------------+--------+--------
woof | 0.14 | 0.94
quack | 0.87 | 0.12
(2 rows)
当然应该在单个查询中完成,对吧?
我会为此使用 window 函数:
select ret_val, value1, value2
from (select s.*, count(*) over (partition by key1, key2) as cnt
from sandbox
) s
where cnt = 1;
请注意,您也可以使用聚合来执行此操作,但我认为查询不那么干净:
select max(ret_val) as ret_val, max(value1) as value1, max(value2) as value2
from sandbox
group by key1, key2
having count(*) = 1;
这里的逻辑是,如果组中只有一行,则 max()
returns 该行中的值。
这里是加入版本:
SELECT ret_val,value1,value2 from sandbox,
( SELECT key1,key2 from sandbox group by 1,2 HAVING count(*)=1 ) as keys
where sandbox.key1 = keys.key1 and sandbox.key2 = keys.key2
select
min(ret_val) as ret_val,
min(val1) as val1,
min(val2) as val2
from sandbox
group by key1, key2
having count(*) = 1;
我认为这应该很简单,但我不知所措。我想在 SQL 语句 HAVING 子句中未使用的列中 return 数据,而不必执行第二次查询。我正在使用 PostgreSQL,但这应该是一个相当普遍的问题。这是数据:
CREATE TABLE sandbox (
ret_val character(10),
key1 character(10),
key2 character(10),
value1 real,
value2 real
);
COPY sandbox (ret_val, key1, key2, value1, value2) FROM stdin;
baa DEF Book 0.800000012 0.270000011
oink GHI Play 0.200000003 0.280000001
Oink DEF Book 0.300000012 0.109999999
chirp GHI Play 0.100000001 0
woof DEF Play 0.400000006 0.300000012
meow DEF Play 0.699999988 0.219999999
woof ABC Book 0.140000001 0.939999998
baa ABC Play 0.25999999 0.75
meow ABC Play 0.75999999 0.150000006
neigh DEF Movie 0.970000029 0.349999994
cluck DEF Movie 0.870000005 0.550000012
quack GHI Movie 0.870000005 0.119999997
\.
我想 return (ret_val, value1, value2) 中的值仅用于 (key1,key2) 对唯一的情况。所以首先我使用 HAVING:
做一个 SELECT=> SELECT key1,key2 from sandbox group by 1,2 HAVING count(*)=1;
key1 | key2
------------+------------
GHI | Movie
ABC | Book
(2 rows)
看到有两个独特的行。然后我 select 使用 HAVING 的输出我需要的数据:
=> SELECT ret_val,value1,value2 from sandbox where
(key1='ABC' and key2='Book') OR (key1='GHI' and key2='Movie');
ret_val | value1 | value2
------------+--------+--------
woof | 0.14 | 0.94
quack | 0.87 | 0.12
(2 rows)
当然应该在单个查询中完成,对吧?
我会为此使用 window 函数:
select ret_val, value1, value2
from (select s.*, count(*) over (partition by key1, key2) as cnt
from sandbox
) s
where cnt = 1;
请注意,您也可以使用聚合来执行此操作,但我认为查询不那么干净:
select max(ret_val) as ret_val, max(value1) as value1, max(value2) as value2
from sandbox
group by key1, key2
having count(*) = 1;
这里的逻辑是,如果组中只有一行,则 max()
returns 该行中的值。
这里是加入版本:
SELECT ret_val,value1,value2 from sandbox,
( SELECT key1,key2 from sandbox group by 1,2 HAVING count(*)=1 ) as keys
where sandbox.key1 = keys.key1 and sandbox.key2 = keys.key2
select
min(ret_val) as ret_val,
min(val1) as val1,
min(val2) as val2
from sandbox
group by key1, key2
having count(*) = 1;