Sql 不按SELECT中的所有非聚合列分组的HAVING子句

Sql 不按SELECT中的所有非聚合列分组的HAVING子句,sql,sas,proc-sql,Sql,Sas,Proc Sql,不按SELECT中的所有非聚合列分组的HAVING子句 我经常遇到具有id列和月份列以及许多其他指标的表。我根据其他列剔除某些行。我只想识别所有12个月数据的id,因此我执行以下操作: proc sql; create table t as SELECT * FROM T1 GROUP BY id HAVING COUNT(id) = 12 quit; 这似乎对我有效,但我想知道这种方法是否有任何危险。我知道我可以只使用id和id计数来连接聚合子查询,但是这种方

不按SELECT中的所有非聚合列分组的HAVING子句 我经常遇到具有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语句中不使用聚合函数?

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

select * 


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

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

select * 


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

使用GROUP BY子句时,所选值必须从为该组选择的一列或聚合函数的结果中派生出来。这是因为在关系代数模型中无法保证选择哪条记录——某些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这并不总是强制的,取决于实现或特定情况,但我始终喜欢可预测的结果。

当使用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这并不总是根据具体情况强制执行或要求执行,但我始终喜欢可预测的结果。

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

注意:查询需要将摘要统计信息重新合并回原始数据

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

在幕后。没有技术上的理由不这样做,除非你的工作站点要求有干净的日志,在这种情况下你不会这样做。这不是非常危险,但同时,为什么不显式地编写加入?

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

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
注意:查询需要将摘要统计信息重新合并回原始数据

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

在幕后。没有技术上的理由不这样做,除非你的工作站点要求有干净的日志,在这种情况下你不会这样做。这并不太危险,但同时,为什么不显式地编写联接?

PROC SQL SAS在选择所有列并按其中一列分组时不会抛出错误。我并不感到惊讶。sql中的s表示结构
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

是的,不是标准的。另外,我没想到你会发布一个崩溃的查询。谢谢大家的反馈。在上面的示例中,我查看每个组中的行的顺序并不重要,因为我只需要一个计数。在这种情况下,以这种方式使用have不会造成任何伤害……对吗?更一般地说,如果我想对一个特定id的行进行平均或求和,这也不重要……对吗?如果我开始尝试选择最大值或最小值,我会遇到麻烦。至少我是这样理解的。当您选择所有列并按其中一列进行分组时,PROC SQL SAS不会抛出错误。我并不感到惊讶。sql中的s表示结构化的,而不是标准的。另外,我没想到你会发布一个崩溃的查询。谢谢大家的反馈。在上面的示例中,我查看每个组中的行的顺序并不重要,因为我只需要一个计数。在这种情况下,以这种方式使用have不会造成任何伤害……对吗?更一般地说,如果我想对一个特定id的行进行平均或求和,这也不重要……对吗?如果我开始尝试选择最大值或最小值,我会遇到麻烦。至少我是这样理解的。