599 Stimmen

Gibt es eine Max-Funktion in SQL Server, die zwei Werte wie Math.Max in .NET nimmt?

Ich möchte eine Abfrage wie diese schreiben:

SELECT o.OrderId, MAX(o.NegotiatedPrice, o.SuggestedPrice)
FROM Order o

Aber das ist nicht die Art und Weise, wie die MAX Funktion funktioniert, richtig? Es handelt sich um eine Aggregatfunktion, d. h. sie erwartet einen einzigen Parameter und gibt dann das MAX aller Zeilen zurück.

Weiß jemand, wie man es auf meine Art macht?

26 Stimmen

Das ist in den meisten anderen Datenbanken als GREATEST Funktion; SQLite emuliert die Unterstützung, indem es mehrere Spalten in der MAX Aggregat.

8 Stimmen

1 Stimmen

Bei der Suche nach einer Lösung für max(a, b) unten sollten Sie sich die Frage stellen, ob die Syntax oder die Berechnung für "a" und/oder "b" wiederholt werden soll. D.h. wenn "b" aus einer komplexen Berechnung mit viel Syntax abgeleitet wird, dann bevorzugen Sie vielleicht eine Lösung, bei der "b" nur einmal erscheint. Z.B. bedeutet die Lösung "IIF(a>b, a, b)" die Wiederholung von "b" - was syntaktisch hässlich sein könnte, aber die folgende Lösung bedeutet, dass "b" (und "a") nur einmal erscheint: SELECT MAX(WERT) FROM (SELECT a AS VALUE UNION SELECT b AS VALUE) AS T1

562voto

MikeTeeVee Punkte 17130

Wenn Sie SQL Server 2008 (oder höher) verwenden, dann ist dies die bessere Lösung:

SELECT o.OrderId,
       (SELECT MAX(Price)
        FROM (VALUES (o.NegotiatedPrice),(o.SuggestedPrice)) AS AllPrices(Price))
FROM Order o

Alle Anerkennung und Stimmen sollten gehen an Svens Antwort auf eine verwandte Frage, "SQL MAX von mehreren Spalten?"
Ich sage, es ist die " beste Antwort ", denn:

  1. Es ist nicht erforderlich, Ihren Code mit UNIONs und PIVOTs zu verkomplizieren, UNPIVOT's, UDF's und wahnsinnig langen CASE-Anweisungen.
  2. Es ist nicht mit dem Problem der Handhabung von Nullen geplagt, es behandelt sie einfach gut.
  3. Es ist einfach, das "MAX" mit "MIN", "AVG" oder "SUM" zu ersetzen. Sie können jede Aggregatfunktion verwenden, um das Aggregat über viele verschiedene Spalten zu finden.
  4. Sie sind nicht auf die von mir verwendeten Namen beschränkt (z. B. "AllPrices" und "Price"). Sie können Ihre eigenen Namen wählen, um es für den Nächsten leichter lesbar und verständlich zu machen.
  5. Sie können mehrere Aggregate mit der SQL Server 2008-Funktion abgeleitete_tabellen etwa so:
    SELECT MAX(a), MAX(b) FROM (VALUES (1, 2), (3, 4), (5, 6), (7, 8), (9, 10) ) AS MyTable(a, b)

35 Stimmen

+1 einzige Antwort, die keinen Zugriff auf die Erstellung von Prozeduren/Funktionen erfordert!

7 Stimmen

Das ist genau die Art von Antwort, die ich gesucht habe. Die Verwendung von Funktionen ist langsam, und dies wird auch auf Daten funktionieren, was ich brauche.

4 Stimmen

+1 Funktioniert perfekt, besonders bei mehr als 2 zu vergleichenden Spalten!

254voto

splattne Punkte 102178

Kann in einer Zeile erledigt werden:

-- the following expression calculates ==> max(@val1, @val2)
SELECT 0.5 * ((@val1 + @val2) + ABS(@val1 - @val2)) 

Edit : Wenn Sie es mit sehr großen Zahlen zu tun haben, müssen Sie die Wertvariablen in bigint umwandeln, um einen Integer-Überlauf zu vermeiden.

25 Stimmen

+1 Ich glaube, Sie haben den richtigen Weg gewählt. "SELECT ((@val1+@val2) + ABS(@val1-@val2))/2 as MAX_OF_TWO" Denken Sie auch daran, "SELECT ((@val1+@val2) - ABS(@val1-@val2))/2 as MIN_OF_TWO".

7 Stimmen

Dieser Weg führt zu einem Überlauffehler, wenn die Summe größer ist als in einem int gespeichert werden kann: declare @val1 int declare @val2 int set @val1 = 1500000000 set @val2 = 1500000000 SELECT 0.5 * ((@val1 + @val2) + ABS(@val1 - @val2)) -- => Überlauffehler

7 Stimmen

Das habe ich noch nie gesehen. Genial.

186voto

Kevin Crumley Punkte 5706

Sie müssten eine User-Defined Function wenn Sie eine ähnliche Syntax wie in Ihrem Beispiel haben wollten, aber Sie könnten das, was Sie tun wollen, relativ einfach mit einer CASE Erklärung, wie die anderen schon gesagt haben.

El UDF könnte in etwa so aussehen:

create function dbo.InlineMax(@val1 int, @val2 int)
returns int
as
begin
  if @val1 > @val2
    return @val1
  return isnull(@val2,@val1)
end

... und Sie würden es so nennen ...

SELECT o.OrderId, dbo.InlineMax(o.NegotiatedPrice, o.SuggestedPrice) 
FROM Order o

27 Stimmen

Ich würde Ihre Lösung unterstützen, das einzige, was ich hinzufügen würde, ist die Unterstützung für NULL-Werte. Wenn Sie einfach die letzte Zeile ändern: "return @value2" zu lesen als: "return isnull(@val2,@val1)", dann gibt die Funktion, wenn einer der Werte Null ist, den Nicht-Null-Wert zurück, andernfalls funktioniert sie wie gewohnt

2 Stimmen

Was ist mit anderen Datentypen, z. B. müsste ich ein HigherIntegerArgument und ein HigherDateTimeArgument und ein HigherVarcharArgument und ein ... schreiben?

12 Stimmen

Wird dies unglaublich langsam sein, wie alles, was skalare UDFs sind. Verwenden Sie stattdessen Inline-UDFs

139voto

Scott Langham Punkte 55597

Nein, das glaube ich nicht. Ich wollte das neulich haben. Das Nächste, was ich bekam, war:

SELECT
  o.OrderId,
  CASE WHEN o.NegotiatedPrice > o.SuggestedPrice THEN o.NegotiatedPrice 
     ELSE o.SuggestedPrice
  END
FROM Order o

7 Stimmen

Das ist meine Lieblingsmethode. Sie riskieren keinen Überlauf, und es ist weniger kryptisch als splattnes Lösung (die übrigens cool ist), und ich habe nicht die Mühe, eine UDF zu erstellen. case ist in vielen Situationen sehr praktisch.

1 Stimmen

SELECT o.OrderId, CASE WHEN o.NegotiatedPrice > o.SuggestedPrice OR o.SuggestedPrice IS NULL THEN o.NegotiatedPrice ELSE o.SuggestedPrice END FROM Order o

1 Stimmen

Wenn Sie anstelle von "o.NegotiatedPrice" einen Begriff wie "(datediff(day, convert(datetime, adr_known_since, 120), getdate())-5)*0.3" verwenden, müssen Sie diesen Code wiederholen. Alle zukünftigen Änderungen des Terms müssen zweimal durchgeführt werden. Eine Funktion vom Typ min(x, y, ...) wäre viel schöner

129voto

Xin Punkte 27823

Warum nicht versuchen IIF Funktion (erfordert SQL Server 2012 und höher)

IIF(a>b, a, b)

Das war's.

(Tipp: Seien Sie vorsichtig mit einem der beiden "would be null , da das Ergebnis von a>b ist immer dann falsch, wenn einer von beiden null ist. Also b wird in diesem Fall das Ergebnis sein)

7 Stimmen

Wenn einer der Werte NULL wird das Ergebnis immer das zweite sein.

6 Stimmen

IIF() ist ein syntaktischer Zucker für die CASE-Anweisung. Wenn einer der beiden Werte der CASE-Bedingung NULL ist, ist das Ergebnis das zweite (ELSE).

0 Stimmen

@xxyzzy das ist weil NULL > 1234 Aussage ist falsch

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X