HAVING子句没有按SELECT
中的所有非聚合列分组
我经常遇到具有id列和月份列以及许多其他指标的表。我根据其他列清除了某些行。我只想要拥有所有12个月数据的id,所以我会做以下事情:
proc sql;
create table t as
SELECT *
FROM T1
GROUP BY id
HAVING COUNT(id) = 12
quit;
它似乎对我有用,但我想知道这种方法是否有任何危险。我知道我可以加入只有id和id数的聚合子查询,但这种方法更容易向非sql用户解释。
一般情况下,您是否可以仅使用HAVING
中的几个列GROUP BY
子句而SELECT
语句中没有聚合函数?
答案 0 :(得分:2)
这取决于数据库。在我的一个(redbrick)上,你提出的查询会抛出一个错误。为了使它工作,我必须改变
select *
到
select id.
然而,你可能有误入歧途的动机。我通常对获得正确答案的最有效方法感兴趣。对自己和任何可能需要维护它的人来说,清晰也很重要,但对外行的清晰度不是我的优先事项之一。
答案 1 :(得分:1)
当使用GROUP BY子句时,所选值必须 1 可以从为该组选择的列之一或聚合函数的结果中派生。这是因为关系代数模型中没有关于选择哪条记录的保证 - 某些SQL方言(例如SQL Server)会拒绝这样的构造并出错!
现在,假设我们希望所有记录负责保持此条件(即“选择非分组/聚合列”),我们可以使用连接。连接是一种处理此类展示RA的简单方法,但不同的数据库可能支持使用不同结构的相同结果。
select t.* from (
select id
from T1
group by id
having count(id) = x) as g
left join T1 as t
on t.id = g.id
但是,这与以下不同(在SQL Server中无效):
select * -- ONLY the id column value is "well-defined" !!
from T1
group by id
having count(id) = x
因为在后一种情况下,每组只选择一条记录。这也是为什么只使用定义组的列或从该组聚合的列。
1 这并不总是强制执行(取决于实施)或要求(取决于具体情况),但我总是喜欢可预测的结果。
答案 2 :(得分:1)
NOTE: The query requires remerging summary statistics back with the original data
。
SAS实际上执行的查询与pst
的答案相同:
select t.* from (
select id
from T1
group by id
having count(id) = x) as g
left join T1 as t
on t.id = g.id
在幕后。没有技术原因可以不这样做,除非您的工作现场要求有干净的日志(在这种情况下您不会)。它不是非常冒险,但与此同时,为什么不明确地写入连接?
答案 3 :(得分:1)
select t.* from (
select id
from T1
group by id
having count(id) = x) as g
left join T1 as t
on t.id = g.id