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?

skb
źródło
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
Kevin Crumley
źródł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)
MikeTeeVee
źródło
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.

splattne
źródło
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
Scott Langham
źródł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)

Xin
źródło
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)
jbeanky
źródło
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

źródł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
LukStorms
źródło
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
Martin Smith
źródł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).

SetFreeByTruth
źródło
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.

kristof
źródło
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;
Uri Abramson
źródło
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
Tom Arleth
źródł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
Sam Saffron
źródło
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
scradam
źródło
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
Mark Brackett
źródło
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.

deepee1
źródło
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))
jahu
źródło
1

Możesz zrobić coś takiego:

select case when o.NegotiatedPrice > o.SuggestedPrice 
then o.NegotiatedPrice
else o.SuggestedPrice
end
Per Hornshøj-Schierbeck
źródło
1
SELECT o.OrderID
CASE WHEN o.NegotiatedPrice > o.SuggestedPrice THEN
 o.NegotiatedPrice
ELSE
 o.SuggestedPrice
END AS Price
Wayne
źródło
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
andrewc
źródło
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
jsmink
źródło
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
Steve Ford
źródł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
mohghaderi
źródło
0
select OrderId, (
    select max([Price]) from (
        select NegotiatedPrice [Price]
        union all
        select SuggestedPrice
    ) p
) from [Order]
błąd
źródło
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;
Ashraf Mohammed
źródł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
Chris Porter
źródło
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;
Pustynny Orzeł
źródło
-1

W Presto możesz użyć

SELECT array_max(ARRAY[o.NegotiatedPrice, o.SuggestedPrice])
maxymoo
źródło