sql - 聚合(分组依据)如何在 SQL Server 上工作?

标签 sql 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语句及其执行计划是这样的:
alt text

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

最佳答案

通常是 Stream AggregateHash Aggregate .

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

  • 让我们看看如何AVG作品。它需要两个状态变量:sumcount
    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 , 并扫描排序后的结果集:

    石斑鱼值(value)总和计数
    -- 进入
    -- 变量: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
    

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

    哈希更快是结果集未排序(哈希比排序快)。
    MINMAX是特殊情况,因为它们不需要扫描整个组:仅扫描组内聚合列的第一个和最后一个值。

    不幸的是,SQL Server与大多数其他系统不同,不能有效地利用它,因为它不擅长做 INDEX SKIP SCAN (跳过不同的索引键)。

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

    关于sql - 聚合(分组依据)如何在 SQL Server 上工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1471147/

    相关文章:

    java - 当表名包含空格时,通过 JDBC 从 FileMaker 表中选择

    php - 在 PHP 中比较一个查询和多个结果

    sql-server - 在 SQL Server 中使用正则表达式

    sql - 需要 sql 帮助 : For each record in table A (has more columns than table B), 插入表 B

    sql sum 按多列分组

    c# - TIME(2) 列的值显示为带有额外的精度零,而查询仅返回 2

    sql - 仅当传递的参数具有值时才使用 Where 子句中的 'Exists'

    sql - 字符串日期格式转换为日期

    php - MS SQL 2005 自动递增错误

    mysql - 根据mysql中的另一列从列中检索数据