Sybase:HAVING在行上运行?

时间:2013-03-19 18:38:38

标签: sql sybase-ase

我遇到了以下SYBASE SQL:

-- Setup first
create table #t (id int, ts int)
go

insert into #t values (1, 2)
insert into #t values (1, 10)
insert into #t values (1, 20)
insert into #t values (1, 30)

insert into #t values (2, 5)
insert into #t values (2, 13) 
insert into #t values (2, 25)
go

declare @time int select @time=11
-- This is the SQL I am asking about
select * from (select * from #t where ts <= @time) t group by id having ts = max(ts)
go

此SQL的结果是

 id          ts          
 ----------- ----------- 
           1          10 
           2           5 

这看起来像HAVING条件应用于行而不是组。有人请指点我在Sybase 15.5文档中描述这种情况吗?我所看到的只是“HAVING在群体上运作”。我在文档中看到的最接近的是:

  

having子句可以包含不在的列或表达式   选择列表而不是group by子句。

(引自here)。

然而,他们并没有准确解释当你这样做时会发生什么。

3 个答案:

答案 0 :(得分:1)

我没有完成Sybase,因为它与MS SQL Server共享代码.... 90年代,但我对你所做的解释是:

首先,列表被过滤为&lt; = 11

id   ts
1    2
1    10
2    5

其他所有内容都被过滤掉了。

接下来,您将列表过滤到TS =该组的最大值(TS)的行。

id   ts
1    10
2    5

10是组1的最大值(TS),5是组2的最大值(TS)。这两行是剩余的行。你会有什么结果呢?

答案 1 :(得分:1)

如果您阅读文档here,则having子句中未出现在group by子句中的Sybase使用的列似乎与MySQL不同。

他们给出的例子有这样的解释:

  

Transact-SQL扩展列,价格(在选择列表中,但不是   一个聚合而不是在group by子句中,导致所有合格的   要在每个限定组中显示的行,即使是标准组也是如此   by子句为每个组生成一行。该群体仍受影响   向量聚合,计算每组的平均价格   显示在每个组的每一行上(它们的值相同)   计算例如a):

所以,ts = max(ts)基本上是这样做的:

select *
from (select t.*,
             max(ts) over (partition by id) as maxts
      from #t
      where ts <= @time
     ) t
where ts = maxts

子查询很重要,因为where子句用于max()计算将返回所有行。

我发现这种行为相当混乱和不标准。我会用更典型的结构替换它。这些复杂程度大致相同,对更多的受众来说似乎更清晰。

答案 2 :(得分:1)

我的理解:是的,从根本上说,HAVING在行上运行。通过省略GROUP BY,它可以在单个“超级组”内的所有结果行上操作,而不是在组内的行上操作。阅读原始链接的Sybase docco中的“如何分组并使用聚合查询工作”部分: -

  

如何分组和查询聚合工作

     
      
  • where 子句排除不符合搜索条件的行;对于分组或非分组查询,其功能保持不变。
  •   
  • group by 子句将剩余的行收集到组中表达式中的每个唯一值的一个组中。省略分组可为整个表创建一个组。
  •   
  • 选择列表中指定的聚合函数计算每个组的汇总值。对于标量聚合,表只有一个值。向量聚合计算不同组的值。
  •   
  • 子句从结果中排除不符合其搜索条件的组。即使具有子句仅测试行, group by 子句的存在与否也可能使其看起来在组上运行:   
        
    • 当查询包含分组时, 会排除结果组行。这就是 似乎对群组进行操作的原因。
    •   
    • 如果查询没有分组,则 会从(单组)表中排除结果行。这就是 似乎对行进行操作的原因(结果类似于 where 子句的结果)。
    •   
  •   

其次,简要摘要出现在"How the having, group by, and where clauses interact"部分: -

  

拥有,分组和where子句如何互动

     

如果在查询中包含拥有分组其中子句,则每个子句影响行的顺序决定最终结果:

     
      
  • where 子句排除不符合其搜索条件的行。
  •   
  • group by 子句将剩余的行收集到表达式中的每个唯一值的一个组中。
  •   
  • 选择列表中指定的聚合函数计算每个组的汇总值。
  •   
  • 子句会排除最终结果中不符合搜索条件的行。
  •   

@ SQLGuru的解释是对此的一个例证。

编辑...

在相关的一点上,我对使用TSQL“扩展列”的非ANSI符合查询的行为感到惊讶。 Sybase在WHERE子句(ii)之后处理扩展列(i),方法是创建对原始表的额外连接,(iii) WHERE在连接中不使用子句。这样的查询可能会返回比预期更多的行,然后HAVING子句需要额外的条件来过滤掉这些行。

查看示例 b c d “Transact-SQL扩展中,在原始链接的docco的页面上分组并拥有”。我发现从Sybase安装 pubs2 示例数据库与示例一起使用很有用。