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

37voto

jbeanky Punkte 450
DECLARE @MAX INT
@MAX = (SELECT MAX(VALUE) 
               FROM (SELECT 1 AS VALUE UNION 
                     SELECT 2 AS VALUE) AS T1)

1 Stimmen

Ich gebe dieser Lösung ein +1, weil sie DRY-konform ist (wiederhole dich nicht), ohne dass eine UDF geschrieben werden muss. Es ist auch großartig, wenn beide Werte, die Sie überprüfen müssen, die Ergebnisse anderer Sql sind, z.B. in meinem Fall möchte ich den größeren von 2 select count(*) Anweisungen finden.

2 Stimmen

Ich hasse es, dass ich auf diese Lösung zurückgreifen muss, aber es ist mit Sicherheit der beste Weg, es in SQL Server zu tun, bis sie native Unterstützung für GREATEST oder in-line MAX hinzufügen. Vielen Dank für die Entsendung es - +1 für Sie!

19voto

LukStorms Punkte 28049

In SQL Server 2012 oder höher können Sie eine Kombination aus IIF y ISNULL (oder COALESCE ), um das Maximum von 2 Werten zu erhalten.
Auch wenn 1 von ihnen NULL ist.

IIF(col1 >= col2, col1, ISNULL(col2, col1)) 

Oder wenn Sie wollen, dass es 0 zurückgibt, wenn beide NULL sind

IIF(col1 >= col2, col1, COALESCE(col2, col1, 0)) 

Beispiel Ausschnitt:

-- use table variable for testing purposes
declare @Order table 
(
  OrderId int primary key identity(1,1),
  NegotiatedPrice decimal(10,2),
  SuggestedPrice decimal(10,2)
);

-- Sample data
insert into @Order (NegotiatedPrice, SuggestedPrice) values
(0, 1),
(2, 1),
(3, null),
(null, 4);

-- Query
SELECT 
     o.OrderId, o.NegotiatedPrice, o.SuggestedPrice, 
     IIF(o.NegotiatedPrice >= o.SuggestedPrice, o.NegotiatedPrice, ISNULL(o.SuggestedPrice, o.NegotiatedPrice)) AS MaxPrice
FROM @Order o

Ergebnis:

OrderId NegotiatedPrice SuggestedPrice  MaxPrice
1       0,00            1,00            1,00
2       2,00            1,00            2,00
3       3,00            NULL            3,00
4       NULL            4,00            4,00

Aber wenn man das Maximum von mehreren Spalten braucht?
Dann schlage ich eine CROSS APPLY auf eine Aggregation der VALUES vor.

Exemple :

SELECT t.*
, ca.[Maximum]
, ca.[Minimum], ca.[Total], ca.[Average]
FROM SomeTable t
CROSS APPLY (
   SELECT 
    MAX(v.col) AS [Maximum], 
    MIN(v.col) AS [Minimum], 
    SUM(v.col) AS [Total], 
    AVG(v.col) AS [Average]
   FROM (VALUES (t.Col1), (t.Col2), (t.Col3), (t.Col4)) v(col)
) ca

Dies hat den zusätzlichen Vorteil, dass gleichzeitig auch andere Dinge berechnet werden können.

14voto

Chris Rogers Punkte 1663

Versuchen Sie dies. Es kann mehr als 2 Werte verarbeiten

SELECT Max(v) FROM (VALUES (1), (2), (3)) AS value(v)

0 Stimmen

Super! Ich habe eine Lösung mit GREATEST die auf unserem AZURE SQL Server läuft, aber diese Lösung läuft auch auf meinem Desktop SQL Server Express

0 Stimmen

Dies ist die beste Lösung. Vor allem, wenn Ihre Werte von komplexen Funktionen abgeleitet sind.

13voto

Die anderen Antworten sind gut, aber wenn Sie sich Sorgen um NULL-Werte machen müssen, sollten Sie diese Variante wählen:

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

2 Stimmen

Das einzige erforderliche ISNULL steht nach dem ELSE. Der anfängliche ">"-Vergleich gibt false zurück und geht zum ELSE über, wenn einer der beiden Werte bereits null ist.

12voto

Martin Smith Punkte 417623

Unterabfragen können auf die Spalten der äußeren Abfrage zugreifen, so dass Sie Folgendes verwenden können dieser Ansatz Aggregate zu verwenden, wie zum Beispiel MAX über Spalten hinweg. (Wahrscheinlich ist es nützlicher, wenn eine größere Anzahl von Spalten betroffen ist)

;WITH [Order] AS
(
SELECT 1 AS OrderId, 100 AS NegotiatedPrice, 110 AS SuggestedPrice UNION ALL
SELECT 2 AS OrderId, 1000 AS NegotiatedPrice, 50 AS SuggestedPrice
)
SELECT
       o.OrderId, 
       (SELECT MAX(price)FROM 
           (SELECT o.NegotiatedPrice AS price 
            UNION ALL SELECT o.SuggestedPrice) d) 
        AS MaxPrice 
FROM  [Order]  o

1 Stimmen

Toll! Es lässt sich sehr gut vergrößern.

1 Stimmen

+1 um denjenigen Liebe zu zeigen, die noch im Jahr 2005 sind. Ich weiß nicht, wie ich diese Antwort übersehen konnte. Unter der Haube funktioniert sie bestimmt genauso gut wie das, was ich 2 Jahre später gepostet habe. Im Nachhinein hätte ich das erkennen und Ihre Antwort aktualisieren sollen, um die neuere Syntax von 2008 zu berücksichtigen. Tut mir leid, ich wünschte, ich könnte meine Punkte jetzt mit Ihnen teilen.

1 Stimmen

@MikeTeeVee - Danke! Ja, unter der Haube wird der Plan derselbe sein. Aber die VALUES Die Syntax ist schöner.

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