Categorias:

Funções de agregação , Funções de janela

HASH_AGG

Retorna um valor agregado de hash assinado de 64 bits sobre o conjunto (não ordenado) de linhas de entrada. HASH_AGG nunca retorna NULL, mesmo que nenhuma entrada seja fornecida. “Hashes” de entrada vazia para 0.

Um uso para funções de hash agregado é detectar mudanças em um conjunto de valores sem comparar os valores individuais antigos e novos. HASH_AGG pode calcular um único valor do hash baseado em muitas entradas; quase qualquer mudança em uma das entradas provavelmente resultará em uma mudança na saída da função HASH_AGG. Comparar duas listas de valores normalmente requer a ordenação de ambas as listas, mas HASH_AGG produz o mesmo valor independentemente da ordem das entradas. Como os valores não precisam ser classificados para HASH_AGG, o desempenho é normalmente muito mais rápido.

Nota

HASH_AGG não é uma função de hash criptográfico e não deve ser usada como tal.

Para fins criptográficos, utilizar as famílias de funções SHA (em Funções de cadeia de caracteres e binários).

Consulte também

HASH

Sintaxe

Função de agregação

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

HASH_AGG(*)
Copy

Função de janela

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

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

Notas de uso

  • A forma HASH_AGG(*) calcula em todas as colunas. Isto funciona tanto para a função agregada quanto para a função de janela.

  • HASH_AGG calcula uma “impressão digital” em toda uma tabela ou janela ou resultado de consulta. Qualquer mudança na entrada influenciará o resultado de HASH_AGG com uma probabilidade esmagadora. Isso pode ser usado para detectar rapidamente mudanças no conteúdo das tabelas ou resultados de consultas.

    Note que é possível, embora muito improvável, que duas tabelas de entrada diferentes produzam o mesmo resultado para HASH_AGG. Se você precisar ter certeza de que duas tabelas ou resultados de consulta que produzem o mesmo resultado HASH_AGG realmente contêm os mesmos dados, você ainda deve comparar os dados quanto à igualdade (por exemplo, usando o operador MINUS). Para obter mais detalhes, consulte Operadores de conjuntos.

  • HASH_AGG não diferencia a ordem (ou seja, a ordem das linhas em uma tabela de entrada ou resultado de consulta não influencia o resultado de HASH_AGG). No entanto, alterar a ordem das colunas de entrada faz alterar o resultado.

  • HASH_AGG aplica hash nas linhas de entrada individuais usando a função HASH. Os recursos salientes desta função são transferidos para HASH_AGG. Em particular, o HASH_AGG é estável no sentido de que quaisquer duas linhas que comparam de forma igual e que tenham tipos compatíveis aplicam garantidamente hash no mesmo valor (ou seja, influenciam o resultado de HASH_AGG da mesma forma).

    Por exemplo, mudar a escala e a precisão de uma coluna que faz parte de alguma tabela, não altera o resultado de HASH_AGG sobre essa tabela. Consulte HASH para obter mais detalhes.

  • Ao contrário da maioria das outras funções agregadas, HASH_AGG não ignora entradas NULL (isto é, entradas NULL influenciam no resultado de HASH_AGG).

  • Tanto para a função agregada quanto para funções de janela, as linhas duplicadas, incluindo as linhas todas NULL duplicadas, influenciam o resultado. A palavra-chave DISTINCT pode ser usada para suprimir o efeito de linhas duplicadas.

  • Quando usado como uma função de janela:

    • Esta função não oferece suporte para:

      • Subcláusula ORDER BY na cláusula OVER().

      • Quadros de janela.

Detalhes do agrupamento

No impact.

  • Duas cadeias de caracteres que são idênticas mas têm especificações de agrupamento diferentes têm o mesmo valor do hash. Em outras palavras, apenas a cadeia de caracteres, não a especificação do agrupamento, afeta o valor do hash.

  • Duas cadeias de caracteres que são diferentes, mas que se comparam de maneira igual de acordo com um agrupamento, podem ter um valor do hash diferente. Por exemplo, duas cadeias de caracteres que são idênticas usando agrupamento que não identifica pontuação normalmente terão valores de hash diferentes porque apenas a cadeia de caracteres, não a especificação de agrupamento, afeta o valor de hash.

Exemplos

NULLs nunca são ignorados:

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

Hashes de entrada vazia para 0:

select hash_agg(null) where 0 = 1;

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

Use HASH_AGG(*) para agregar convenientemente em todas as colunas de entrada:

select hash_agg(*) from orders;

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

A agregação agrupada é suportada:

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

Suprimir linhas duplicadas usando DISTINCT (as linhas duplicadas influenciam os resultados de 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

Este exemplo final calcula o número de dias em que os conjuntos correspondentes de clientes com pedidos com status não igual a 'F' e status não igual a 'P', respectivamente, são idênticos:

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

Observe que a consulta não leva em conta a possibilidade de colisões de hash, portanto o número real de dias pode ser um pouco menor.