Kategorien:

Aggregatfunktionen, Fensterfunktionen

HASH_AGG

Gibt einen aggregierten, signierten 64-Bit-Hash-Wert für die (ungeordnete) Menge von Eingabezeilen zurück. HASH_AGG gibt niemals NULL zurück, auch wenn keine Eingabe bereitgestellt wird. Leere Eingabe „hasht“ zu 0.

Ein Anwendungsfall für Hash-Aggregatfunktionen ist das Erkennen von Änderungen an einer Gruppe von Werten, ohne die einzelnen alten und neuen Werte zu vergleichen. HASH_AGG kann aus vielen Eingabewerten einen einzigen Hash-Wert berechnen, wobei wahrscheinlich fast jede Änderung an einem der Eingabewerte zu einer Änderung des Ausgabewerts der HASH_AGG-Funktion führt. Beim Vergleich von zwei Wertelisten müssen normalerweise beide Listen sortiert werden, HASH_AGG erzeugt jedoch unabhängig von der Reihenfolge der Eingaben denselben Wert. Da die Werte nicht nach HASH_AGG sortiert werden müssen, ist die Leistung normalerweise deutlich schneller.

Bemerkung

HASH_AGG ist keine kryptografische Hashfunktion und sollte nicht als solche verwendet werden.

Nutzen Sie für kryptografische Zwecke die SHA-Funktionsfamilie (siehe Zeichenfolgen- und Binärfunktionen).

Siehe auch:

HASH

Syntax

Aggregatfunktion

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

HASH_AGG(*)

Fensterfunktionen

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

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

Nutzungshinweise

  • Das Formular HASH_AGG(*) führt die Berechnung über alle Spalten aus. Dies funktioniert sowohl für die Aggregatfunktion als auch für die Fensterfunktion.

  • HASH_AGG berechnet einen „Fingerabdruck“ für eine ganze Tabelle oder ein Abfrageergebnis. Jede Änderung an der Eingabe beeinflusst das Ergebnis von HASH_AGG mit überwältigender Wahrscheinlichkeit. So lassen sich Änderungen an Tabelleninhalten oder Abfrageergebnissen schnell erkennen.

    Beachten Sie, dass es möglich, wenn auch sehr unwahrscheinlich ist, dass zwei verschiedene Eingabetabellen dasselbe Ergebnis für HASH_AGG liefern. Wenn Sie überprüfen möchten, ob zwei Tabellen oder Abfrageergebnisse, die dasselbe HASH_AGG-Ergebnis liefern, tatsächlich dieselben Daten enthalten, müssen Sie die Daten weiter hinsichtlich ihrer Gleichheit vergleichen (z. B. mit dem Operator MINUS). Weitere Details dazu finden Sie unter Mengenoperatoren.

  • HASH_AGG ist nicht sensibel für die Reihenfolge (d. h. die Reihenfolge von Zeilen in einer Eingabetabelle oder in einem Abfrageergebnis hat keinen Einfluss auf das Ergebnis von HASH_AGG). Durch Ändern der Reihenfolge von Eingabespalten wird das Ergebnis jedoch geändert.

  • HASH_AGG „hasht“ einzelne Eingabezeilen mithilfe der Funktion HASH. Die herausragenden Merkmale dieser Funktion werden auf HASH_AGG übertragen. Insbesondere ist HASH_AGG in dem Sinne stabil, dass beliebige zwei Zeilen, die gleiche Werte haben und kompatible Typen aufweisen, garantiert auf den gleichen Wert gehasht werden (d. h. sie beeinflussen das Ergebnis von HASH_AGG auf gleiche Weise).

    Wenn Sie beispielsweise die Skalierung und Genauigkeit einer Spalte ändern, die Teil einer Tabelle ist, ändert sich das Ergebnis von HASH_AGG für die Tabelle nicht. Weitere Informationen finden Sie unter HASH.

  • Im Gegensatz zu den meisten anderen Aggregatfunktionen ignoriert HASH_AGG NULL-Eingaben nicht (d. h. NULL-Eingaben beeinflussen das Ergebnis von HASH_AGG).

  • Sowohl für die Aggregatfunktion als auch für die Fensterfunktionen wirken sich doppelte Zeilen, einschließlich Komplett-NULL-Zeilen, auf das Ergebnis aus. Das Schlüsselwort DISTINCT kann verwendet werden, um die Wirkung duplizierter Zeilen zu unterdrücken.

  • Bei Verwendung als Fensterfunktion:

    • Diese Funktion unterstützt nicht:

      • ORDER BY-Unterklausel in der OVER()-Klausel

      • Fensterrahmen

Sortierungsdetails

No impact.

  • Zwei identische Zeichenfolgen mit unterschiedlichen Sortierungsspezifikationen haben denselben Hashwert. Mit anderen Worten: Nur die Zeichenfolge, nicht die Sortierungsspezifikation, wirkt sich auf den Hashwert aus.

  • Zwei Zeichenfolgen, die unterschiedlich sind, aber gemäß einer Sortierung gleich sind, können unterschiedliche Hashwerte aufweisen. Beispielsweise haben zwei Zeichenfolgen, die bei Verwendung einer Sortierung ohne Berücksichtigung von Satzzeichen identisch sind, normalerweise unterschiedliche Hashwerte, da sich nur die Zeichenfolge und nicht die Sortierungsspezifikation auf den Hashwert auswirkt.

Beispiele

NULLs werden nie ignoriert:

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       |
----------------------+----------------------+----------------------------+

Leere Eingaben hashen zu 0:

select hash_agg(null) where 0 = 1;

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

Verwenden von HASH_AGG(*) zum einfachen Aggregieren aller Eingabespalten:

select hash_agg(*) from orders;

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

Gruppierte Aggregation wird unterstützt:

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  |
-------------------+----------------------+

Unterdrücken doppelter Zeilen mit DISTINCT (doppelte Zeilen beeinflussen das Ergebnis von 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                       |
-------------------+-------------------------------------------+

In diesem letzten Beispiel wird die Anzahl der Tage berechnet, an denen die übereinstimmenden Kundengruppen mit Aufträgen, deren Status ungleich 'F' und ungleich 'P' ist, identisch sind:

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               |
--------------------+

Beachten Sie, dass bei der Abfrage die Möglichkeit von Hash-Kollisionen nicht berücksichtigt wird, sodass die tatsächliche Anzahl von Tagen möglicherweise etwas niedriger ist.