1

在没有按所有非聚合列分组的 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吗?

4

4 回答 4

2

这取决于数据库。在我的一个(红砖)上,您提出的查询将引发错误。为了让它发挥作用,我必须改变

select * 

select id.  

但是,您可能有错误的动机。我通常对获得正确答案的最有效方法感兴趣。对我自己和其他任何可能需要维护它的人来说清楚也很重要,但对非专业人士来说清楚并不是我的优先事项之一。

于 2013-03-19T18:23:34.307 回答
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
于 2013-08-20T10:04:14.540 回答
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这并不总是强制执行(取决于实施)或要求(取决于具体情况),但我一直喜欢可预测的结果。

于 2013-03-19T19:19:29.703 回答
1

SAS 将允许您这样做,当然,在其 SQL 实现中(您的标签表明您正在使用 SAS 的实现)。您将在日志中收到一条注释:

NOTE: The query requires remerging summary statistics back with the original data.

pstSAS 实际上执行与's answer中相同的查询:

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

在幕后。没有技术原因不这样做,除非您在工作现场要求拥有干净的日志(在这种情况下您不会)。这不是非常冒险,但同时,为什么不明确地写加入呢?

于 2013-03-20T14:59:34.740 回答