Czy w programie SQL Server jest funkcja Max, która przyjmuje dwie wartości, takie jak Math.Max ​​w .NET?


488

Chcę napisać takie zapytanie:

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

Ale nie tak MAXdziała ta funkcja, prawda? Jest to funkcja agregująca, więc oczekuje pojedynczego parametru, a następnie zwraca MAX wszystkich wierszy.

Czy ktoś wie jak to zrobić po swojemu?


13
Jest to zaimplementowane w większości innych baz danych jako GREATESTfunkcja; SQLite emuluje obsługę, dopuszczając wiele kolumn w MAXagregacji.
— OMG Kucyki


Znajdując rozwiązanie dla maks. (A, b) poniżej, pamiętaj o pytaniu, czy chcesz powtórzyć składnię lub obliczenia dla „a” i / lub „b”. To znaczy, jeśli „b” pochodzi ze złożonego obliczenia zawierającego wiele składni, możesz preferować rozwiązanie, w którym „b” pojawia się tylko raz. Np. Rozwiązanie „IIF (a> b, a, b)” oznacza powtarzanie „b” - co może być brzydkie pod względem składniowym, jednak poniższe rozwiązanie oznacza, że ​​„b” (i „a”) pojawiają się tylko raz: WYBIERZ MAKS (WARTOŚĆ) OD (WYBIERZ JAKO WARTOŚĆ UNION WYBIERZ b JAKO WARTOŚĆ) AS T1
— Andrew Jens

Odpowiedzi:


158

Musisz zrobić a, User-Defined Functionjeśli chcesz mieć składnię podobną do twojego przykładu, ale czy możesz zrobić to, co chcesz, wstawiać, dość łatwo z CASEinstrukcją, jak powiedzieli inni.

UDFMoże być coś takiego:

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

... i nazwałbyś to tak ...

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

24
Chciałbym wesprzeć twoje rozwiązanie, jedyne, co chciałbym dodać, to obsługa wartości NULL. Jeśli po prostu zmodyfikujesz ostatnią linię: „return @ wartość2” i odczyta jako: „return isnull (@ val2, @ val1)”, to jeśli jedna z wartości ma wartość null, funkcja zwróci wartość inną niż null, w przeciwnym razie będzie działać jako normal
— kristof 24.09.08

1
Co z innymi typami danych, np. Czy musiałbym napisać HigherIntegerArgument i HigherDateTimeArgument i HigherVarcharArgument i ...?
— dniu

9
będzie to niezwykle powolne, ponieważ wszystkie rzeczy skalarne UDF. Zamiast tego użyj wbudowanych UDF
— AK

12
@xan Nie mam pojęcia, co przyszło mi do głowy, kiedy zadałem to pytanie. Oczywiście nie za dużo. W każdym razie dzięki za odpowiedź.
— Thomas

13
@Thomas obowiązkowe meme obraz (bez obrazy przeznaczone do was w żaden sposób!) Flickr.com/photos/16201371@N00/2375571206
— Xan

468

Jeśli używasz programu SQL Server 2008 (lub nowszego), jest to lepsze rozwiązanie:

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

Wszystkie kredyty i głosy powinny przejść do odpowiedzi Svena na powiązane pytanie „SQL MAX wielu kolumn?”
Mówię, że to „ najlepsza odpowiedź ”, ponieważ:

  1. Nie wymaga komplikowania kodu za pomocą instrukcji UNION, PIVOT, UNPIVOT, UDF i szalonych CASE.
  2. Nie jest nękany problemem radzenia sobie z zerami, radzi sobie z nimi dobrze.
  3. Zamiana „MAX” na „MIN”, „AVG” lub „SUM” jest łatwa. Możesz użyć dowolnej funkcji agregującej, aby znaleźć agregację w wielu różnych kolumnach.
  4. Nie jesteś ograniczony do nazw, których użyłem (tj. „AllPrices” i „Price”). Możesz wybrać własne imiona, aby ułatwić czytanie i zrozumienie dla następnego faceta.
  5. Można znaleźć wiele agregatów za pomocą tabel pochodnych SQL Server 2008, takich jak:
    WYBIERZ MAKS (a), MAKS (b) OD (WARTOŚCI (1, 2), (3, 4), (5, 6), (7, 8), (9, 10)) AS MyTable (a, b)

27
+1 tylko odpowiedź, która nie wymaga dostępu do tworzenia procedury / funkcji!
— Alex

6
Właśnie tego rodzaju odpowiedzi szukałem. Używanie funkcji jest powolne i będzie to działać również w terminach, czego potrzebuję.
— Johann Strydom

3
+1 Działa idealnie, szczególnie dla porównania więcej niż 2 kolumn!
— JanW

11
Jest to mniej wydajne niż rozwiązanie CASE WHEN, które wymaga jedynie obliczenia skalara.
— tekumara

5
Chociaż prostsza składnia może nigdy nie być warta spadku wydajności przy ustalaniu MAKSU 2 wartości, może być inna sprawa z większą liczbą wartości. Nawet po uzyskaniu MAKS 4 wartości klauzule CASE stają się długie, niezdarne i podatne na błędy, jeśli są generowane ręcznie, podczas gdy klauzula VALUES pozostaje prosta i jasna.
— Typhlosaurus

220

Można to zrobić w jednym wierszu:

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

Edycja: Jeśli masz do czynienia z bardzo dużymi liczbami, musisz przekonwertować zmienne wartości na bigint, aby uniknąć przepełnienia liczb całkowitych.


18
+1 Uważam, że podałeś najodpowiedniejszy sposób. „SELECT ((@ val1 + @ val2) + ABS (@ val1- @ val2)) / 2 jako MAX_OF_TWO” Pamiętaj również, „SELECT ((@ val1 + @ val2) - ABS (@ val1- @ val2)) / 2 jako MIN_OF_TWO „.
— tom

6
W ten sposób pojawi się błąd przepełnienia, jeśli suma jest większa niż może być zapisana w wartości int: deklaracja @ val1 int deklaracja @ val2 int set @ val1 = 1500000000 set @ val2 = 1500000000 WYBIERZ 0,5 * ((@ val1 + @ val2) + ABS (@ val1 - @ val2)) - => błąd przepełnienia
— AakashM

89
To niezwykle „brudna” „sztuczka”. Podczas programowania Twój kod powinien wyraźnie wyrażać cel, jednak w twoim przypadku wygląda to na kod pobrany z konkursu zaciemniania.
— greenoldman

24
Może to być „brudne”, ale może to być jedyna opcja dla baz danych z prostymi dialektami SQL.
— splattne 11.01.11

12
Nie zgadzam się z marcias. Kod niekoniecznie musi sam wyraźnie wyrażać cel, o ile komentarze pozwalają go wypracować. Jeśli wykonujesz jakieś skomplikowane równania matematyczne w kodzie (lub gdziekolwiek), czasem trudno jest sprawić, by było samoopisowe. Tak długo, jak dzieli się na prostsze, łatwiejsze do zrozumienia części, jest to prawidłowe programowanie.
— Rob

127

Nie wydaje mi się Chciałem to kiedyś. Najbliżej było:

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

4
To moja ulubiona metoda. Nie ryzykujesz przepełnienia, a to jest mniej tajemnicze niż rozwiązanie Splattne (co jest fajne przy okazji), a ja nie mam problemu z tworzeniem UDF. futerał jest bardzo przydatny w wielu sytuacjach.
— Lance Fisher

WYBIERZ o.OrderId, PRZYPADEK, GDY o.Negocjowana cena> o.S Sugerowana cena LUB o.S Sugerowana cena JEST NULLOWA NASTĘPNIE o o.Negocjowana cena INNE o.
— Sugerowana

Gdy zamiast „o.NegotiationPrice” masz raczej termin podobny do „(data, data, konwersja (datetime, adr_known_since, 120), getdate ()) - 5) * 0.3” musisz powtórzyć ten kod. Wszelkie przyszłe zmiany tego terminu należy wprowadzić dwukrotnie. Funkcja typu min (x, y, ...) byłaby znacznie ładniejsza
— Daniel

87

Dlaczego nie wypróbować funkcji IIF (wymaga programu SQL Server 2012 i nowszych)

IIF(a>b, a, b)

Otóż ​​to.

(Wskazówka: bądź ostrożny null, ponieważ jedno z a>bnich byłoby fałszywe , ponieważ wynik będzie fałszywy, gdy którykolwiek z nich będzie zerowy. Tak też bbędzie w tym przypadku)


7
Jeśli jedną z wartości jest NULL, wynikiem będzie zawsze druga.
— jahu

4
IIF () jest cukrem syntaktycznym dla instrukcji CASE. Jeśli którakolwiek wartość warunku CASE jest równa NULL, wynikiem będzie druga (ELSE).
— xxyzzy

@xxyzzy to dlatego, że NULL > 1234instrukcja jest fałszywa
— Xin

8
tak IIF(a>b, a, COALESCE(b,a))aby podać wartość, gdy istnieje tylko jeden
— MPAG

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

Daję temu rozwiązaniu +1, ponieważ jest zgodny z DRY (nie powtarzaj się) bez potrzeby zapisywania UDF. Jest również świetny, jeśli obie wartości, które musisz sprawdzić, są wynikami innych SQL, np. W moim przypadku chcę znaleźć większą z 2 instrukcji select count (*).
— MikeKulls

1
Nienawidzę, że muszę uciekać się do tego rozwiązania, ale z pewnością jest to najlepszy sposób, aby to zrobić w SQL Server, dopóki nie dodadzą natywnej obsługi NAJWIĘKSZEJ lub wbudowanej MAX. Dziękujemy za opublikowanie - +1 dla Ciebie!
— SqlRyan

10

Inne odpowiedzi są dobre, ale jeśli musisz się martwić o wartości NULL, możesz chcieć tego wariantu:

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
Jedyny wymagany ISNULL jest po ELSE. Początkowe porównanie „>” zwróci false i przejdzie do ELSE, jeśli którakolwiek z wartości jest już pusta.
— Phil B

10

W SQL Server 2012 lub nowszym możesz użyć kombinacji IIFi ISNULL(lub COALESCE), aby uzyskać maksymalnie 2 wartości.
Nawet jeśli 1 z nich ma wartość NULL.

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

Lub jeśli chcesz, aby zwracał 0, gdy oba mają wartość NULL

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

Przykładowy fragment:

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

Wynik:

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

Ale czy trzeba SUMOWAĆ wiele wartości?
Następnie sugeruję KRZYŻ ZASTOSOWAĆ do agregacji WARTOŚCI.
Ma to również tę zaletę, że może obliczyć inne rzeczy w tym samym czasie.

Przykład:

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

Zapytania podrzędne mogą uzyskiwać dostęp do kolumn z zapytania zewnętrznego, dzięki czemu można użyć tego podejścia do użycia agregatów, takich jak MAXmiędzy kolumnami. (Prawdopodobnie bardziej przydatne, gdy zaangażowana jest większa liczba kolumn)

;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

Miły! Bardzo dobrze się skaluje.
— greenoldman

+1, by pokazać Miłość do tych jeszcze w 2005 roku. Nie wiem, jak przeoczyłem tę odpowiedź. Pod przykrywkami wyobrażam sobie, że działa równie dobrze, jak to, co napisałem 2 lata później. Z perspektywy czasu powinienem był to zrozumieć i zaktualizować twoją odpowiedź w celu uwzględnienia wówczas nowszej składni z 2008 roku. Przepraszam, chciałbym podzielić się z tobą moimi punktami.
— MikeTeeVee,

@MikeTeeVee - Dzięki! Tak, pod przykryciem plan będzie taki sam. Ale VALUESskładnia jest ładniejsza.
— Martin Smith,

6

SQL Server 2012 wprowadził IIF:

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

Podczas używania zalecane jest używanie wartości NULL IIF, ponieważ NULLpo obu stronach boolean_expressionbędą IIFzwracane wartości false_value(w przeciwieństwie do NULL).


Twoje rozwiązanie nie będzie dobrze obsługiwać wartości NULL, gdy druga wartość będzie ujemna, zwróci wartość null
— t-clausen.dk

5

Wybrałbym rozwiązanie dostarczone przez kcrumley. Po prostu zmodyfikuj go nieco, aby obsługiwał wartości NULL

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

EDYCJA Zmodyfikowano po komentarzu Marka . Jak słusznie zauważył w 3 wartościowej logice x> NULL lub x <NULL zawsze powinien zwracać NULL. Innymi słowy nieznany wynik.


1
Wartości zerowe są ważne. I ważne jest, aby postępować z nimi konsekwentnie. Jedyną prawidłową odpowiedzią na Jest NULL> x jest NULL.
— Mark Brackett,

Masz rację, zmodyfikuję moją odpowiedź, aby to odzwierciedlić, dzięki za zwrócenie na to uwagi
— Kristof

Jeśli przekażemy liczbę całkowitą i NULL, myślę, że bardziej powszechne jest zwracanie wartości innej niż null, więc funkcja działa jako kombinacja Max (x, y) i ISNULL (x, y). Dlatego osobiście zmieniłbym ostatnią linię na: return ISNULL (@ val1, @ val2) - co, co prawda, prawdopodobnie był tym, co
— musiałeś

@ the-locster, patrz komentarz Marka
— Kristof

1
będzie to niezwykle powolne, ponieważ wszystkie rzeczy skalarne UDF. Zamiast tego użyj wbudowanych UDF
— AK

4

To takie proste:

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;

Zobacz komentarz @Neil do poprzedniej odpowiedzi WYBIERZ dbo.InlineMax (CAST (0,5 AS FLOAT), 100) jest niepoprawny.
— 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

Aby uzyskać wyjaśnienia, zapoznaj się z tym artykułem: red-gate.com/simple-talk/sql/sql-training/…
— Tom Arleth

2
Nie dołączaj potrzebnych informacji do swojego kodu tylko za pomocą linku. Wyobraź sobie, że ten link wygaśnie pewnego dnia, a Twoja odpowiedź będzie wtedy bezużyteczna. Więc proszę, dodaj informacje niezbędne bezpośrednio w swojej odpowiedzi. Ale nadal możesz podać ten link jako źródło informacji dla innych osób, aby szukać dalszych informacji w górę.
— L. Guthardt,

3

Ups, właśnie opublikowałem duplikat tego pytania ...

Odpowiedź brzmi: nie ma wbudowanej funkcji takiej jak Greatest Oracle , ale podobny wynik można uzyskać dla 2 kolumn z UDF, zauważ, że użycie sql_variant jest tutaj bardzo ważne.

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

Wysłałem tę odpowiedź:

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
Uwaga: implementacja NAJWIĘKSZEJ funkcji dopasuje zachowanie Oracle dla 2 parametrów, jeśli jakikolwiek parametr ma wartość NULL, zwróci wartość NULL
— Sam Saffron

2
Należy zachować ostrożność podczas korzystania z sql_variant. Twoja funkcja da nieoczekiwany wynik w następującej sytuacji: WYBIERZ dbo.greatest (CAST (0,5 AS FLOAT), 100)
— Neil

@ Neil ma rację (nauczyłem się tego na własnej skórze), jak ulepszysz tę funkcję, aby zapobiec tego rodzaju problemom?
— Luca,

3

Oto przykład przypadku, który powinien obsługiwać wartości zerowe i działać ze starszymi wersjami MSSQL. Jest to oparte na funkcji inline w jednym z popularnych przykładów:

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

2

Prawdopodobnie nie zrobiłbym tego w ten sposób, ponieważ jest mniej wydajny niż wspomniane już konstrukcje CASE - chyba że być może masz indeksy obejmujące oba zapytania. Tak czy inaczej, jest to przydatna technika dla podobnych problemów:

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

W przypadku powyższej odpowiedzi dotyczącej dużych liczb można wykonać mnożenie przed dodawaniem / odejmowaniem. Jest trochę nieporęczny, ale nie wymaga obsady. (Nie umiem mówić o szybkości, ale zakładam, że wciąż jest dość szybki)

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

Zmiany w

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

przynajmniej alternatywa, jeśli chcesz uniknąć rzucania.


2

Oto wersja IIF z obsługą NULL (na podstawie odpowiedzi Xina):

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

Logika jest następująca: jeśli jedna z wartości jest równa NULL, zwróć tę, która nie jest równa NULL (jeśli obie są równe NULL, zwracana jest wartość NULL). W przeciwnym razie zwróć większą.

To samo można zrobić dla MIN.

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

1

Możesz zrobić coś takiego:

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

W najprostszej formie ...

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

W przypadku programu SQL Server 2012:

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

1

Oto odpowiedź @ Scott Langham z prostą obsługą NULL:

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;

Chociaż ciekawe użycie tego typu VALUESinline, nie jestem pewien, czy jest to prostsze niż CASElub IFF. Byłbym zainteresowany, aby zobaczyć, jak wydajność tego rozwiązania wypada w porównaniu z innymi opcjami
— Chris Schaller

0

Rozwijając odpowiedź Xin i zakładając, że typem wartości porównawczej jest INT, to podejście również działa:

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

To jest pełny test z przykładowymi wartościami:

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

W MemSQL wykonaj następujące czynności:

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

W Presto możesz użyć

SELECT array_max(ARRAY[o.NegotiatedPrice, o.SuggestedPrice])
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.