SQL Greatest(), least()

Größter oder kleinster Wert der Argumente


Apache DerbyBigQueryDb2 (LUW)H2MariaDBMySQLOracle DBPostgreSQLSQL ServerSQLite200520072009201120132015201720192021⊘ 3.5.7 - 3.43.0b⚠ 2022a⊘ 2008R2 - 2019⚠ 8.4 - 16c⚠ 8.3a✓ 11gR1 - 21c✓ 5.0 - 8.0.34✓ 5.1 - 10.11⚠ 2.0.202 - 2.1.214c⚠ 1.4.198 - 1.4.200c⚠ 1.4.191 - 1.4.197ac✓ 9.7 - 11.5.8✓ 2.0⊘ 10.15.1.3 - 10.16.1.1
  1. ⚡Nicht-konforme Null-Behandlung
  2. Alternative: Skalare Min- und Max-Funktionen
  3. Nicht-konforme Behandlung von Null-Elementen in Zeilen-Werten

Die SQL-Funktionen Greatest (größter) und Least (kleinster) akzeptieren ein oder mehrere✓✗ Argumente und liefern den größten oder kleinsten Wert, wenn keines der Argumente Null ist✓✗.

SELECT GREATEST(1, 2, 3)
  FROM …

Greatest und Least sind skalare Funktionen. Anders als die Aggregatfunktionen Min und Max betrachten sie jede Zeile einzeln.

Null-Behandlung

Der SQL-Standard legt fest, dass Greatest und Least den Null-Wert liefern, sobald eines der Argumente Null ist. Das ist also anders als bei den meisten Aggregatfunktionen, insbesondere Min und Max. Während Min und Max Null-Werte ignorieren und den kleinsten oder größten Wert der restlichen Menge liefern, respektieren Greatest und Least Null-Werte insofern, als dass die Präsenz eines einzelnen Null-Wertes bedeutet, dass der größte oder kleinste Werte nicht zweifelsfrei feststellbar ist.

BigQueryDb2 (LUW)H2MariaDBMySQLOracle DBPostgreSQLSQL Serverrespektieren nullignorieren null

Wie man in der Tabelle sehen kann, wird die vom Standard vorgesehene Null-Behandlung nicht immer umgesetzt. Das ist auch keine Überraschung, da Greatest und Least oft schon Jahrzehnte bevor sie 2023 in den Standard aufgenommen wurden, verfügbar waren.

Ich persönlich denke, dass die Standardisierung von Greatest und Least mit strikter Respektierung von Null-Werten nicht die beste Entscheidung war. Der SQL-Standard wird ohnehin nicht sehr genau befolgt. Neues Verhalten einzufordern, das Jahrzehnte alten Implementierungen0 widerspricht, macht es nicht besser, da sich die alten Implementierungen wahrscheinlich nicht an den neuen Standard anpassen werden. Da beide Varianten Null-Werte zu behandelt schon seit geraumer Zeit im Umlauf sind, hätte keine der Varianten zum Standard erhoben werden sollen. Es ist einfach ein weiteres Verhalten, dass durch die Umsetzung vorgegeben wird.1

Hinweis in eigener Sache

Ich biete SQL Schulungen, Optimierung und Beratung an. Auch der Kauf meines Buches „SQL Performance Explained“ (ab €9,95) unterstützt meine Arbeit an dieser Webseite.

In die Zukunft blickend hoffe ich, dass die Benutzer die Wahl haben werden. Zum Beispiel mit respect nulls und ignore nulls-Angaben, wie es sie bei manchen Window-Funktionen gibt.

LEAST(…) [ RESPECT NULLS | IGNORE NULLS ]

Die Filter-Klausel, wie man sie von Aggregatfunktionen kennt, wäre zwar generischer, löst aber das Problem der Umsetzungen nicht, die Null-Werte schon lange ignorieren.

Zeilenwerte

In Standard-SQL kann ein Wert, dessen Vergleich mit einem einzigen anderen Wert unknown ergibt, nicht das Ergebnis von Greatest oder Least sein.

Angewendet auf die folgenden Beispiele bedeutet das, dass ⓵ and ⓶ jeweils den ersten Wert liefern, weil es keinen anderen Wert gibt, der noch kleiner sein könnte.

⓵ LEAST( ROW(1   ,    1),  ROW(1,    2) )
⓶ LEAST( ROW(1   , null),  ROW(2, null) )
⓷ LEAST( ROW(1   , null),  ROW(1, null) )
⓸ LEAST( ROW(null,    1),  ROW(9,    2) )

Falls du dich bezüglich ⓶ wunderst bedenke, dass Bereichsvergleiche auf Zeilenwerte zweifelsfrei festgelegt sind, wenn ein Präfix eine zweifelsfreie Antwort gibt. Das ist im Beispiel ⓷ nicht der Fall: Obwohl beide Werte ununterscheidbar sind, sind sie entsprechend der normalen Vergleichsregeln für Null nicht gleich. Ein Kleiner-gleich-Vergleich (<=) liefert unknown. Bei keinem Wert kann ausgeschlossen werden, dass es einen noch kleineren gibt, sodass Least den Null-Wert liefert. Das Gleiche gilt für Beispiel ⓸. Da das erste Element eines Wertes Null ist, ergeben alle Vergleiche mit diesem Wert unknown. Es kann keinen Wert geben, der zweifelsfrei kleiner-gleich allen anderen ist. Least liefert wieder Null. Das sind lediglich die Folgen des normalen Verhaltens von Null in SQL: Null stellt Ungewissheit dar, Ungewissheit breitet sich aus.

BigQueryDb2 (LUW)H2MariaDBMySQLOracle DBPostgreSQLSQL Serverkeine nullzweifelsfreier Präfix ⓶weder gleich noch unterscheidbar ⓷ein Präfix ist null

Auch hier ist es keine Überraschung, dass sich alte Systeme nicht entsprechend dem neuen Standard verhalten. Die wenigen der getesteten Systeme, die Greatest und Least mit Zeilenwerten unterstützen, wenden eine Logik auf Basis einer Sortierung an, d.h. sie behandeln Null-Elemente als größt- oder kleinst-möglichen Wert. Ob es ein besonders großer oder kleiner Wert ist, hängt vom System ab – wie auch bei Default-Sortierung von Null-Werte in der Order By-Klausel (ID133). Zum Glück machen es die Systeme bei Greatest und Least genauso, wie sie es auch bei Order By machen.

BigQueryDb2 (LUW)H2MariaDBMySQLOracle DBPostgreSQLSQL Serverstandard-konformsortiert als größter Wertsortiert als kleinster Wert

Limits

Der SQL-Standard sieht für Greatest und Least ein oder mehrere Argumente vor. In der Praxis gibt es einige Systeme die den (wenig nützlichen) Ein-Argument-Fall nicht unterstützen. Die Obergrenze liegt meist jenseits meiner Tests.

BigQueryDb2 (LUW)H2MariaDBMySQLOracle DBPostgreSQLSQL Server1 Parameter2 Parameters254 Parameters255 Parameters10 000 Parameters

Alternativen

Manche SQL-Dialekte haben skalare Varianten der Funktionen Min und Max, die mehrere Argument akzeptieren und den kleinsten oder größten davon liefern.

Apache DerbyBigQueryDb2 (LUW)aH2MariaDBMySQLOracle DBPostgreSQLSQL ServerSQLitebskalares min und max
  1. Respektiert Null-Werte: Ein Null-Wert mach das Ergebnis Null
  2. Respektiert Null-Werte: Ein Null-Wert mach das Ergebnis Null • Nicht-konformer Umgang mit Collations

Normative Referenzen

Die Funktionen Greatest und Least bilden die optionale Funktion T054, „GREATEST and LEAST“.

20 Jahre SQL-Evolution kann man nicht an einem Tag nachholen. Abonniere den Newsletter via E-Mail, Twitter oder RSS, um sukzessive aufzuholen und modern-sql.com am Radar zu behalten.

Über den Autor

Foto von Markus Winand

Markus Winand gibt auf modern-sql.com Einblick in SQL und zeigt, wie es von verschiedenen Systemen unterstützt wird. Zuvor machte er use-the-index-luke.com, was er noch immer wartet. Markus kann als Trainer, Sprecher und Berater auf winand.at engagiert werden.

Sein Buch kaufen

Titelbild von „SQL Performance Explained“: Eichhörnchen läuft durchs Grass

Die Essenz: SQL-Tuning auf 200 Seiten

Jetzt Kaufen
(Taschenbuch und/oder PDF)

Sein Training

Markus verwandelt veraltetes SQL-92-Wissen in solides und zeitgemäßes SQL-Know-how

Erfahren Sie mehr»

Fußnoten

  1. Die älteste, nicht-konforme Umsetzung die ich gefunden habe ist PostgreSQL 8.1 aus 2005.

  2. Ab SQL:2023 hat jedes Verhalten, das durch die Umsetzung vorgegeben ist (implementation-defined) eine ID und ein Namen. Teil 2 hat 360 davon.

Mit Markus Winand verbinden

Markus Winand auf LinkedInMarkus Winand auf XINGMarkus Winand auf Twitter
„modern SQL“ von Markus Winand ist unter einer Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License lizenziert.
Impressum | Kontakt | KEINE GEWÄHR | Handelsmarken | Datenschutz und DSGVO | CC-BY-NC-ND 3.0 Lizenz