类别:

聚合函数窗口函数

HASH_AGG

返回输入行的(无序)集合上的汇总签名 64 位哈希值。HASH_AGG 从不返回 NULL,即使没有提供输入。将输入“哈希值”清空为 0

聚合哈希函数的一个用途是检测对一组值的更改,而无需比较单个旧值和新值。HASH_AGG 可以基于多个输入计算单个哈希值;几乎对其中一个输入的任何更改都可能导致 HASH_AGG 函数输出的更改。比较两个值列表通常需要对两个列表进行排序,但无论输入的顺序如何,HASH_AGG 都会生成相同的值。因为不需要对 HASH_AGG 的值进行排序,所以性能通常要快得多。

备注

HASH_AGG 不是 加密哈希函数,不应用作加密哈希函数。

如需加密,请使用 SHA 系列函数(在 字符串和二进制函数 中)。

另请参阅:

HASH

语法

聚合函数

HASH_AGG( [ DISTINCT ] <expr> [ , <expr2> ... ] )

HASH_AGG(*)
Copy

窗口函数

HASH_AGG( [ DISTINCT ] <expr> [ , <expr2> ... ] ) OVER ( [ PARTITION BY <expr3> ] )

HASH_AGG(*) OVER ( [ PARTITION BY <expr3> ] )
Copy

使用说明

  • HASH_AGG(*) 形式对所有列进行计算。这适用于聚合函数和窗口函数。

  • HASH_AGG 计算整个表或查询结果或窗口的“指纹”。输入的任何更改都会以压倒性的概率影响 HASH_AGG 结果。这可用于快速检测对表内容或查询结果的变更。

    请注意,尽管可能性很小,但两个不同的输入表可能会为 HASH_AGG 产生相同的结果。如果需要确保生成相同 HASH_AGG 结果的两个表或查询结果确实包含相同的数据,则仍必须比较数据是否相等(例如,通过使用 MINUS 运算符)。有关更多详细信息,请参阅 集运算符

  • HASH_AGG 区分顺序(即输入表或查询结果中的行顺序不会影响 HASH_AGG 的结果)。但是,更改输入列的顺序 确实 会更改结果。

  • HASH_AGG 使用 HASH 函数对各个输入行进行哈希处理。此函数的显著特征延续到 HASH_AGG。特别是,从某种意义上说,HASH_AGG 是 稳定的,因为任何两行比较相等且具有兼容类型,都可以保证哈希为相同的值(即它们以相同的方式影响 HASH_AGG 结果)。

    例如,更改属于某个表的列的小数位数和精度不会更改该表上的 HASH_AGG 结果。有关详细信息,请参阅 HASH

  • 与大多数其他聚合函数相比,HASH_AGG 不忽略 NULL 输入(即 NULL 输入会影响 HASH_AGG 结果)。

  • 对于聚合函数和窗口函数,重复的行(包括重复的所有 NULL 行)都会影响结果。DISTINCT 关键字可用于抑制重复行的效果。

  • 用作窗口函数时:

    • 此函数不支持:

      • OVER() 子句中的 ORDER BY 分子句。

      • 窗口框架。

排序规则详细信息

No impact.

  • 如果两个字符串实际相同,但具有不同的排序规则规范,则它们具有相同的哈希值。换句话说,只有字符串(而不是排序规则规范)会影响哈希值。

  • 如果根据排序规则,两个字符串实际不同,但在比较时却被视为相等,则它们可能具有不同的哈希值。例如,使用不区分标点符号的排序规则的两个相同字符串通常具有不同的哈希值,因为只有字符串(而不是排序规则规范)会影响哈希值。

示例

NULLs 永远不会忽视:

select hash_agg(null), hash_agg(null, null), hash_agg(null, null, null);

----------------------+----------------------+----------------------------+
    HASH_AGG(NULL)    | HASH_AGG(NULL, NULL) | HASH_AGG(NULL, NULL, NULL) |
----------------------+----------------------+----------------------------+
 -5089618745711334219 | 2405106413361157177  | -5970411136727777524       |
----------------------+----------------------+----------------------------+
Copy

将输入哈希值清空为 0

select hash_agg(null) where 0 = 1;

----------------+
 HASH_AGG(NULL) |
----------------+
 0              |
----------------+
Copy

使用 HASH_AGG(*) 方便地汇总所有输入列:

select hash_agg(*) from orders;

---------------------+
     HASH_AGG(*)     |
---------------------+
 1830986524994392080 |
---------------------+
Copy

支持分组聚合:

select year(o_orderdate), hash_agg(*) from orders group by 1 order by 1;

-------------------+----------------------+
 YEAR(O_ORDERDATE) |     HASH_AGG(*)      |
-------------------+----------------------+
 1992              | 4367993187952496263  |
 1993              | 7016955727568565995  |
 1994              | -2863786208045652463 |
 1995              | 1815619282444629659  |
 1996              | -4747088155740927035 |
 1997              | 7576942849071284554  |
 1998              | 4299551551435117762  |
-------------------+----------------------+
Copy

使用 DISTINCT 禁止重复行(重复行会影响 HASH_AGG结果):

select year(o_orderdate), hash_agg(o_custkey, o_orderdate) from orders group by 1 order by 1;

-------------------+----------------------------------+
 YEAR(O_ORDERDATE) | HASH_AGG(O_CUSTKEY, O_ORDERDATE) |
-------------------+----------------------------------+
 1992              | 5686635209456450692              |
 1993              | -6250299655507324093             |
 1994              | 6630860688638434134              |
 1995              | 6010861038251393829              |
 1996              | -767358262659738284              |
 1997              | 6531729365592695532              |
 1998              | 2105989674377706522              |
-------------------+----------------------------------+

select year(o_orderdate), hash_agg(distinct o_custkey, o_orderdate) from orders group by 1 order by 1;

-------------------+-------------------------------------------+
 YEAR(O_ORDERDATE) | HASH_AGG(DISTINCT O_CUSTKEY, O_ORDERDATE) |
-------------------+-------------------------------------------+
 1992              | -8416988862307613925                      |
 1993              | 3646533426281691479                       |
 1994              | -7562910554240209297                      |
 1995              | 6413920023502140932                       |
 1996              | -3176203653000722750                      |
 1997              | 4811642075915950332                       |
 1998              | 1919999828838507836                       |
-------------------+-------------------------------------------+
Copy

最后一个示例计算状态不等于 'F' 和状态不等于 'P' 的订单的相应客户集分别相同的天数:

select count(distinct o_orderdate) from orders;

-----------------------------+
 COUNT(DISTINCT O_ORDERDATE) |
-----------------------------+
 2406                        |
-----------------------------+

select count(o_orderdate)
from (select o_orderdate, hash_agg(distinct o_custkey)
      from orders
      where o_orderstatus <> 'F'
      group by 1
      intersect
      select o_orderdate, hash_agg(distinct o_custkey)
      from orders
      where o_orderstatus <> 'P'
      group by 1);

--------------------+
 COUNT(O_ORDERDATE) |
--------------------+
 1143               |
--------------------+
Copy

请注意,查询不考虑哈希冲突的可能性,因此实际天数可能略低。

语言: 中文