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


488

Ich möchte eine Abfrage wie folgt schreiben:

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

Aber so funktioniert die MAXFunktion doch nicht , oder? Da es sich um eine Aggregatfunktion handelt, erwartet sie einen einzelnen Parameter und gibt dann die MAX aller Zeilen zurück.

Weiß jemand, wie es auf meine Weise geht?


13
Dies ist in den meisten anderen Datenbanken als GREATESTFunktion implementiert . SQLite emuliert die Unterstützung, indem mehrere Spalten im MAXAggregat zugelassen werden.
OMG Ponys


Beachten Sie bei der Suche nach einer Lösung für max (a, b) die Frage, ob die Syntax oder Berechnung für "a" und / oder "b" wiederholt werden soll. Das heißt, wenn "b" aus einer komplexen Berechnung mit viel Syntax abgeleitet wird, bevorzugen Sie möglicherweise eine Lösung, bei der "b" nur einmal vorkommt. ZB bedeutet die Lösung "IIF (a> b, a, b)" das Wiederholen von "b" - was syntaktisch hässlich sein könnte, die folgende Lösung bedeutet jedoch, dass "b" (und "a") nur einmal erscheinen: SELECT MAX (VALUE) VON (SELECT a AS VALUE UNION SELECT b AS VALUE) AS T1
Andrew Jens

Antworten:


158

Sie müssten eine erstellen, User-Defined Functionwenn Sie eine Syntax ähnlich Ihrem Beispiel haben möchten, aber könnten Sie das, was Sie tun möchten, inline ziemlich einfach mit einer CASEAnweisung tun , wie die anderen gesagt haben.

Das UDFkönnte so etwas sein:

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

... und du würdest es so nennen ...

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

24
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: "return @ value2" so ändern, dass sie lautet: "return isnull (@ val2, @ val1)", wenn einer der Werte null ist, gibt die Funktion den Wert ungleich null zurück, andernfalls funktioniert sie als normal
kristof

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

9
Dies wird unglaublich langsam sein, da alle Dinge skalare UDFs. Verwenden Sie stattdessen Inline-UDFs
AK

12
@xan Ich habe keine Ahnung, was mir durch den Kopf ging, als ich diese Frage tatsächlich stellte. Natürlich nicht zu viel. Trotzdem danke für die Antwort.
Thomas

13
@ Thomas Obligatorisches Meme-Bild (in keiner Weise für Sie bestimmt!) Flickr.com/photos/16201371@N00/2375571206
xan

468

Wenn Sie SQL Server 2008 (oder höher) verwenden, 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 Gutschriften und Stimmen sollten an Svens Antwort auf eine verwandte Frage gehen: "SQL MAX aus mehreren Spalten?"
Ich sage, es ist die " beste Antwort ", weil:

  1. Es ist nicht erforderlich, Ihren Code mit UNION-, PIVOT-, UNPIVOT-, UDF- und verrückt langen CASE-Anweisungen zu komplizieren.
  2. Es ist nicht mit dem Problem des Umgangs mit Nullen behaftet, es behandelt sie einwandfrei.
  3. Es ist einfach, "MAX" gegen "MIN", "AVG" oder "SUM" auszutauschen. Sie können eine beliebige Aggregatfunktion verwenden, um das Aggregat über viele verschiedene Spalten zu finden.
  4. Sie sind nicht auf die Namen beschränkt, die ich verwendet habe (dh "AllPrices" und "Price"). Sie können Ihre eigenen Namen auswählen, um das Lesen und Verstehen für den nächsten Mann zu erleichtern.
  5. Sie können mehrere Aggregate mithilfe der abgeleiteten Tabellen von SQL Server 2008 wie folgt finden :
    SELECT MAX (a), MAX (b) FROM (VALUES (1, 2), (3, 4), (5, 6), (7, 8), (9, 10)) AS MyTable (a, b)

27
+1 nur Antwort, die keinen Zugriff zum Erstellen von Prozeduren / Funktionen erfordert!
Alex

6
Genau die Art von Antwort, nach der ich gesucht habe. Die Verwendung von Funktionen ist langsam und dies funktioniert auch bei Daten, was ich brauche.
Johann Strydom

3
+1 Funktioniert perfekt, besonders wenn mehr als 2 Spalten verglichen werden sollen!
JanW

11
Dies ist weniger leistungsfähig als die CASE WHEN-Lösung, die nur einen Skalar berechnen muss.
Tekumara

5
Während die einfachere Syntax bei der Bestimmung des MAX von 2 Werten möglicherweise niemals den Leistungseinbruch wert ist, kann es bei mehr Werten eine andere Sache sein. Selbst wenn der MAX von 4 Werten erhalten wird, werden die CASE-Klauseln lang, ungeschickt und fehleranfällig, wenn sie von Hand generiert werden, während die VALUES-Klausel einfach und klar bleibt.
Typhlosaurus

221

Kann in einer Zeile erfolgen:

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

Bearbeiten: Wenn Sie mit sehr großen Zahlen arbeiten, müssen Sie die Wertvariablen in bigint konvertieren, um einen ganzzahligen Überlauf zu vermeiden.


18
+1 Ich glaube, Sie haben den korrektesten Weg angegeben. "SELECT ((@ val1 + @ val2) + ABS (@ val1- @ val2)) / 2 als MAX_OF_TWO" Denken Sie auch daran, "SELECT ((@ val1 + @ val2) - ABS (@ val1- @ val2)) / 2 als MIN_OF_TWO ".
Tom

6
Auf diese Weise wird ein Überlauffehler ausgegeben, wenn die Summe größer ist als in einem int gespeichert werden kann: deklarieren @ val1 int deklarieren @ val2 int set @ val1 = 1500000000 set @ val2 = 1500000000 SELECT 0.5 * ((@ val1 + @ val2) + ABS (@ val1 - @ val2)) - => Überlauffehler
AakashM

89
Dies ist ein extrem "schmutziger" "Trick". Bei der Programmierung sollte Ihr Code das Ziel explizit ausdrücken. In Ihrem Fall sieht es jedoch so aus, als ob Code aus einem Verschleierungswettbewerb stammt.
Greenoldman

24
Es mag "schmutzig" sein, aber es könnte die einzige Option für Datenbanken mit einfachen SQL-Dialekten sein.
Splattne

12
Ich bin nicht einverstanden mit Marcias. Code muss das Ziel nicht unbedingt selbst explizit ausdrücken, solange Kommentare es einem erlauben, es auszuarbeiten. Wenn Sie komplexe mathematische Gleichungen im Code (oder irgendwo anders) ausführen, ist es manchmal schwierig, sie selbstbeschreibend zu machen. Solange es in einfachere, leichter verständliche Teile zerlegt ist, ist das die richtige Programmierung.
Rob

127

Das glaube ich nicht. Ich wollte das neulich. 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

4
Dies ist meine Lieblingsmethode. Sie riskieren keinen Überlauf und es ist weniger kryptisch als die Lösung von splattne (die übrigens cool ist), und ich habe nicht den Aufwand, eine UDF zu erstellen. Fall ist in vielen Situationen sehr praktisch.
Lance Fisher

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

Wenn Sie anstelle von "o.NegotiatedPrice" eher einen Begriff wie "(datiert (Tag, Konvertieren (Datum / Uhrzeit, adr_known_since, 120), getdate ()) - 5) * 0,3" haben, müssen Sie diesen Code wiederholen. Zukünftige Änderungen der Laufzeit müssen zweimal vorgenommen werden. Eine Funktion vom Typ min (x, y, ...) wäre viel schöner
Daniel

87

Probieren Sie die IIF- Funktion aus (erfordert SQL Server 2012 und höher).

IIF(a>b, a, b)

Das ist es.

(Hinweis: Seien Sie vorsichtig mit beiden null, da das Ergebnis von a>bimmer dann falsch ist, wenn eines von beiden null ist. bIn diesem Fall ist dies auch das Ergebnis.)


7
Wenn einer der Werte ist NULL, ist das Ergebnis immer der zweite.
Jahu

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

@xxyzzy das ist, weil NULL > 1234Aussage falsch ist
Xin

8
so IIF(a>b, a, COALESCE(b,a))den Wert zu geben , wenn nur eine vorhanden
MPAG

32
DECLARE @MAX INT
@MAX = (SELECT MAX(VALUE) 
               FROM (SELECT 1 AS VALUE UNION 
                     SELECT 2 AS VALUE) AS T1)

Ich gebe dieser Lösung eine +1, weil sie DRY entspricht (wiederholen Sie sich 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 die größere von 2 select count (*) -Anweisungen finden.
MikeKulls

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

10

Die anderen Antworten sind gut, aber wenn Sie sich Sorgen um NULL-Werte machen müssen, möchten Sie möglicherweise diese Variante:

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

1
Der einzige erforderliche ISNULL ist nach dem ELSE. Der anfängliche ">" Vergleich gibt false zurück und wechselt zu ELSE, wenn einer der Werte bereits null ist.
Phil B

10

In SQL Server 2012 oder höher können Sie eine Kombination aus IIFund ISNULL(oder COALESCE) verwenden, um maximal 2 Werte abzurufen.
Auch wenn einer von ihnen NULL ist.

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

Oder wenn Sie möchten, dass 0 zurückgegeben wird, wenn beide NULL sind

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

Beispielausschnitt:

-- 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 mehrere Werte summieren muss?
Dann schlage ich vor, CROSS APPLY auf eine Aggregation der VALUES anzuwenden.
Dies hat auch den Vorteil, dass dadurch gleichzeitig andere Dinge berechnet werden können.

Beispiel:

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

8

Unterabfragen können über die äußere Abfrage auf die Spalten zugreifen, sodass Sie diesen Ansatz verwenden können , um Aggregate zu verwenden, z. B. MAXspaltenübergreifend. (Wahrscheinlich nützlicher, wenn eine größere Anzahl von Spalten beteiligt 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

Nett! Es skaliert sehr gut.
Greenoldman

+1, um Liebe für diejenigen zu zeigen, die noch im Jahr 2005 sind. Ich weiß nicht, wie ich diese Antwort übersehen habe. Unter dem Deckmantel stelle ich mir vor, dass es genauso gut funktioniert wie das, was ich 2 Jahre später gepostet habe. Im Nachhinein hätte ich dies realisieren und Ihre Antwort aktualisieren müssen, um die neuere Syntax von 2008 aufzunehmen. Entschuldigung, ich wünschte, ich könnte meine Punkte jetzt mit Ihnen teilen.
MikeTeeVee

@ MikeTeeVee - Danke! Ja, unter der Decke wird der Plan der gleiche sein. Aber die VALUESSyntax ist schöner.
Martin Smith

6

SQL Server 2012 eingeführt IIF:

SELECT 
    o.OrderId, 
    IIF( ISNULL( o.NegotiatedPrice, 0 ) > ISNULL( o.SuggestedPrice, 0 ),
         o.NegotiatedPrice, 
         o.SuggestedPrice 
    )
FROM 
    Order o

Die Verwendung von NULL-Werten wird bei der Verwendung empfohlen IIF, da a NULLauf beiden Seiten von Ihnen dazu boolean_expressionführt, dass IIFdie false_value(im Gegensatz zu NULL) zurückgegeben wird.


Ihre Lösung wird NULL nicht gut verarbeiten, wenn der andere Wert negativ ist. Dies wird null zurückgeben
t-clausen.dk

5

Ich würde mich für die von kcrumley bereitgestellte Lösung entscheiden. Ändern Sie sie einfach geringfügig, um NULL-Werte zu verarbeiten

create function dbo.HigherArgumentOrNull(@val1 int, @val2 int)
returns int
as
begin
  if @val1 >= @val2
    return @val1
  if @val1 < @val2
    return @val2

 return NULL
end

BEARBEITEN Geändert nach Kommentar von Mark . Wie er in der 3-wertigen Logik richtig ausgeführt hat, sollte x> NULL oder x <NULL immer NULL zurückgeben. Mit anderen Worten unbekanntes Ergebnis.


1
Nullen sind wichtig. Und es ist wichtig, konsequent damit umzugehen. Die einzig richtige Antwort auf Is NULL> x ist NULL.
Mark Brackett

Sie haben Recht, ich werde meine Antwort ändern, um dies widerzuspiegeln, danke für den Hinweis
kristof

Wenn wir ein int und ein NULL übergeben, ist es meiner Meinung nach üblicher, den Wert ungleich Null zurückzugeben, sodass die Funktion als Kombination aus Max (x, y) und ISNULL (x, y) fungiert. Daher würde ich persönlich die letzte Zeile wie folgt ändern: return ISNULL (@ val1, @ val2) - was zugegebenermaßen wahrscheinlich das ist, womit Sie beginnen mussten :)
redcalx

@ the-locster, siehe Kommentar von Mark
kristof

1
Dies wird unglaublich langsam sein, da alle Dinge skalare UDFs. Verwenden Sie stattdessen Inline-UDFs
AK

4

So einfach ist das:

CREATE FUNCTION InlineMax
(
    @p1 sql_variant,
    @p2 sql_variant
)  RETURNS sql_variant
AS
BEGIN
    RETURN CASE 
        WHEN @p1 IS NULL AND @p2 IS NOT NULL THEN @p2 
        WHEN @p2 IS NULL AND @p1 IS NOT NULL THEN @p1
        WHEN @p1 > @p2 THEN @p1
        ELSE @p2 END
END;

Siehe @ Neil-Kommentar zu einer vorherigen Antwort. SELECT dbo.InlineMax (CAST (0.5 AS FLOAT), 100) ist falsch.
Luca

4
SELECT o.OrderId,   
--MAX(o.NegotiatedPrice, o.SuggestedPrice)  
(SELECT MAX(v) FROM (VALUES (o.NegotiatedPrice), (o.SuggestedPrice)) AS value(v)) as ChoosenPrice  
FROM Order o

Zur Erklärung konsultieren Sie bitte diesen Artikel: red-gate.com/simple-talk/sql/sql-training/…
Tom Arleth

2
Bitte fügen Sie Ihrem Code nicht die erforderlichen Informationen nur über einen Link hinzu. Stellen Sie sich vor, dieser Link läuft eines Tages ab und Ihre Antwort ist dann unbrauchbar. Bitte fügen Sie die wesentlichen Informationen direkt in Ihre Antwort ein. Sie können diesen Link jedoch weiterhin als Ressource für andere bereitstellen, um weitere Informationen nachzuschlagen.
L. Guthardt

3

Hoppla, ich habe gerade einen Betrüger dieser Frage gepostet ...

Die Antwort lautet: Es gibt keine integrierte Funktion wie die von Oracle Greatest , aber Sie können mit einer UDF ein ähnliches Ergebnis für zwei Spalten erzielen. Beachten Sie, dass die Verwendung von sql_variant hier sehr wichtig ist.

create table #t (a int, b int) 

insert #t
select 1,2 union all 
select 3,4 union all
select 5,2

-- option 1 - A case statement
select case when a > b then a else b end
from #t

-- option 2 - A union statement 
select a from #t where a >= b 
union all 
select b from #t where b > a 

-- option 3 - A udf
create function dbo.GREATEST
( 
    @a as sql_variant,
    @b as sql_variant
)
returns sql_variant
begin   
    declare @max sql_variant 
    if @a is null or @b is null return null
    if @b > @a return @b  
    return @a 
end


select dbo.GREATEST(a,b)
from #t

kristof

Gepostet diese Antwort:

create table #t (id int IDENTITY(1,1), a int, b int)
insert #t
select 1,2 union all
select 3,4 union all
select 5,2

select id, max(val)
from #t
    unpivot (val for col in (a, b)) as unpvt
group by id

1
Hinweis: Die Implementierung der GRÖSSTEN Funktion entspricht dem Orakelverhalten für 2 Parameter. Wenn ein Parameter null ist, wird null zurückgegeben
Sam Saffron,

2
Sie sollten vorsichtig sein, wenn Sie sql_variant verwenden. Ihre Funktion wird in der folgenden Situation ein unerwartetes Ergebnis liefern: SELECT dbo.greatest (CAST (0,5 AS FLOAT), 100)
Neil

@Neil hat recht (ich habe es auf die harte Tour gelernt), wie würden Sie diese Funktion verbessern, um diese Art von Problemen zu vermeiden?
Luca

3

Hier ist ein Fallbeispiel, das Nullen verarbeiten sollte und mit älteren Versionen von MSSQL funktioniert. Dies basiert auf der Inline-Funktion in einem der beliebtesten Beispiele:

case
  when a >= b then a
  else isnull(b,a)
end

2

Ich würde es wahrscheinlich nicht so machen, da es weniger effizient ist als die bereits erwähnten CASE-Konstrukte - es sei denn, Sie hätten vielleicht Indizes für beide Abfragen abgedeckt. In beiden Fällen ist es eine nützliche Technik für ähnliche Probleme:

SELECT OrderId, MAX(Price) as Price FROM (
   SELECT o.OrderId, o.NegotiatedPrice as Price FROM Order o
   UNION ALL
   SELECT o.OrderId, o.SuggestedPrice as Price FROM Order o
) as A
GROUP BY OrderId

2

Für die obige Antwort bezüglich großer Zahlen können Sie die Multiplikation vor der Addition / Subtraktion durchführen. Es ist etwas sperriger, erfordert aber keine Besetzung. (Ich kann nicht für Geschwindigkeit sprechen, aber ich gehe davon aus, dass es immer noch ziemlich schnell ist)

SELECT 0.5 * ((@ val1 + @ val2) + ABS (@ val1 - @ val2))

Änderungen an

SELECT @ val1 * 0,5 + @ val2 * 0,5 + ABS (@ val1 * 0,5 - @ val2 * 0,5)

Zumindest eine Alternative, wenn Sie das Casting vermeiden möchten.


2

Hier ist eine IIF-Version mit NULL-Behandlung (basierend auf Xins Antwort):

IIF(a IS NULL OR b IS NULL, ISNULL(a,b), IIF(a > b, a, b))

Die Logik lautet wie folgt: Wenn einer der Werte NULL ist, geben Sie den Wert zurück, der nicht NULL ist (wenn beide NULL sind, wird ein NULL zurückgegeben). Andernfalls geben Sie den größeren zurück.

Gleiches gilt für MIN.

IIF(a IS NULL OR b IS NULL, ISNULL(a,b), IIF(a < b, a, b))

1

Sie können so etwas tun:

select case when o.NegotiatedPrice > o.SuggestedPrice 
then o.NegotiatedPrice
else o.SuggestedPrice
end

1
SELECT o.OrderID
CASE WHEN o.NegotiatedPrice > o.SuggestedPrice THEN
 o.NegotiatedPrice
ELSE
 o.SuggestedPrice
END AS Price

1
CREATE FUNCTION [dbo].[fnMax] (@p1 INT, @p2 INT)
RETURNS INT
AS BEGIN

    DECLARE @Result INT

    SET @p2 = COALESCE(@p2, @p1)

    SELECT
        @Result = (
                   SELECT
                    CASE WHEN @p1 > @p2 THEN @p1
                         ELSE @p2
                    END
                  )

    RETURN @Result

END

1

In seiner einfachsten Form ...

CREATE FUNCTION fnGreatestInt (@Int1 int, @Int2 int )
RETURNS int
AS
BEGIN

    IF @Int1 >= ISNULL(@Int2,@Int1)
        RETURN @Int1
    ELSE
        RETURN @Int2

    RETURN NULL --Never Hit

END

1

Für SQL Server 2012:

SELECT 
    o.OrderId, 
    IIF( o.NegotiatedPrice >= o.SuggestedPrice,
         o.NegotiatedPrice, 
         ISNULL(o.SuggestedPrice, o.NegiatedPrice) 
    )
FROM 
    Order o

1

Hier ist die Antwort von @Scott Langham mit einfacher NULL-Behandlung:

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

0
select OrderId, (
    select max([Price]) from (
        select NegotiatedPrice [Price]
        union all
        select SuggestedPrice
    ) p
) from [Order]

0
 -- Simple way without "functions" or "IF" or "CASE"
 -- Query to select maximum value
 SELECT o.OrderId
  ,(SELECT MAX(v)
   FROM (VALUES (o.NegotiatedPrice), (o.SuggestedPrice)) AS value(v)) AS MaxValue
  FROM Order o;

Obwohl die Verwendung von VALUESInline so interessant ist , bin ich mir nicht sicher, ob dies einfacher ist als CASEoder IFF. Es würde mich interessieren, wie sich die Leistung dieser Lösung im Vergleich zu den anderen Optionen verhält
Chris Schaller,

0

Wenn Sie die Antwort von Xin erweitern und davon ausgehen, dass der Vergleichswerttyp INT ist, funktioniert dieser Ansatz auch:

SELECT IIF(ISNULL(@A, -2147483648) > ISNULL(@B, -2147483648), @A, @B)

Dies ist ein vollständiger Test mit Beispielwerten:

DECLARE @A AS INT
DECLARE @B AS INT

SELECT  @A = 2, @B = 1
SELECT  IIF(ISNULL(@A, -2147483648) > ISNULL(@B, -2147483648), @A, @B)
-- 2

SELECT  @A = 2, @B = 3
SELECT  IIF(ISNULL(@A, -2147483648) > ISNULL(@B, -2147483648), @A, @B)
-- 3

SELECT  @A = 2, @B = NULL
SELECT  IIF(ISNULL(@A, -2147483648) > ISNULL(@B, -2147483648), @A, @B)
-- 2    

SELECT  @A = NULL, @B = 1
SELECT  IIF(ISNULL(@A, -2147483648) > ISNULL(@B, -2147483648), @A, @B)
-- 1

0

Gehen Sie in MemSQL wie folgt vor:

-- DROP FUNCTION IF EXISTS InlineMax;
DELIMITER //
CREATE FUNCTION InlineMax(val1 INT, val2 INT) RETURNS INT AS
DECLARE
  val3 INT = 0;
BEGIN
 IF val1 > val2 THEN
   RETURN val1;
 ELSE
   RETURN val2;
 END IF; 
END //
DELIMITER ;

SELECT InlineMax(1,2) as test;

-1

In Presto können Sie verwenden

SELECT array_max(ARRAY[o.NegotiatedPrice, o.SuggestedPrice])
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.