聚合(分组)如何在SQL Server上工作?

前端之家收集整理的这篇文章主要介绍了聚合(分组)如何在SQL Server上工作?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
sql Server如何实现group by子句(聚合)?

作为灵感,采取this question’s查询的执行计划:

select p_id,DATEDIFF(D,MIN(TreatmentDate),MAX(TreatmentDate)) from 
patientsTable group by p_id

查询数据之前,简单的select语句及其执行计划是这样的:

使用查询和执行计划检索数据后:

通常它是Stream Aggregate或Hash Aggregate.

> Stream aggregate对结果集进行排序,扫描并返回每个新值(不等于扫描中的最后一个值).它允许保留一组聚合状态变量.
>哈希聚合从结果集构建哈希表.每个条目保留聚合状态变量,这些变量在散列未命中时初始化并在散列命中时更新.

让我们看看AVG是如何工作的.它需要两个状态变量:sum和count

grouper  value
1        4
1        3
2        8
1        7
2        1
1        2
2        6
2        3

流聚合

>首先,它需要对值进行排序:

grouper  value
1        4
1        3
1        7
1        2
2        8
2        1
2        6
2        3

>然后,它保留一组状态变量,初始化为0,并扫描排序的结果集:

石斑鱼价值总和
– 进入
– 变量:0 0
1 4 4 1
1 3 7 2
1 7 14 3
1 2 16 4
– 集团变更.返回结果并重新初始化变量
– 返回1,4
– 变量:0 0
2 8 8 1
2 1 9 2
2 6 15 3
2 3 18 4
– 集团变更.返回结果并重新初始化变量
– 返回2,4.5
– 结束

哈希聚合

>只需扫描值并将状态变量保留在哈希表中:

grouper  value
-- Hash miss. Adding new entry to the hash table
--             [1] (0,0)
-- ... and updating it:
1        4     [1] (4,1)
-- Hash hit. Updating the entry:
1        3     [1] (7,2)
-- Hash miss. Adding new entry to the hash table
--             [1] (7,2)  [2] (0,0)
-- ... and updating it:
2        8     [1] (7,2)  [2] (8,1)
1        7     [1] (14,3)  [2] (8,1)
2        1     [1] (14,3)  [2] (9,2)
1        2     [1] (16,4)  [2] (9,2)
2        6     [1] (16,4)  [2] (15,3)
2        3     [1] (16,4)  [2] (18,4)
-- Scanning the hash table and returning the aggregated values
-- 1   4
-- 2   4.5

通常,如果结果集已经排序,则排序更快(例如,值来自索引或由前一操作排序的结果集).

散列更快是结果集未排序(散列比排序更快).

MIN和MAX是特殊情况,因为它们不需要扫描整个组:只有组内聚合列的第一个和最后一个值.

不幸的是,与大多数其他系统不同,sql Server无法有效利用它,因为它不适合进行INDEX SKIP SCAN(跳过不同的索引键).

虽然简单的MAX和MIN(没有GROUP BY子句)如果聚合列上的索引存在,则使用TOP方法,而带有GROUP BY的MIN和MAX使用与其他聚合函数相同的方法.

猜你在找的设计模式相关文章