Có một hàm Max trong SQL Server có hai giá trị như Math.Max ​​trong .NET không?


488

Tôi muốn viết một truy vấn như thế này:

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

Nhưng đây không phải là cách MAXchức năng hoạt động, phải không? Đây là một hàm tổng hợp, vì vậy nó mong đợi một tham số duy nhất và sau đó trả về MAX của tất cả các hàng.

Có ai biết làm theo cách của tôi không?


13
Điều đó được thực hiện trong hầu hết các cơ sở dữ liệu khác như GREATESTchức năng; SQLite mô phỏng hỗ trợ bằng cách cho phép nhiều cột trong MAXtổng hợp.
Ngựa vằn OMG


Khi tìm một giải pháp cho max (a, b) bên dưới, hãy ghi nhớ câu hỏi về việc bạn muốn cú pháp hoặc phép tính cho "a" và / hoặc "b" được lặp lại. Tức là nếu "b" có nguồn gốc từ một phép tính phức tạp liên quan đến nhiều cú pháp thì bạn có thể thích một giải pháp trong đó "b" chỉ xuất hiện một lần. Ví dụ: giải pháp "IIF (a> b, a, b)" có nghĩa là lặp lại "b" - có thể xấu về mặt cú pháp, tuy nhiên giải pháp sau có nghĩa là "b" (và "a") chỉ xuất hiện một lần: CHỌN MAX (GIÁ TRỊ) TỪ (CHỌN MỘT ĐOÀN GIÁ TRỊ NHƯ CHỌN b NHƯ GIÁ TRỊ) NHƯ T1
Andrew Jens

Câu trả lời:


158

Bạn cần phải thực hiện User-Defined Functionnếu bạn muốn có cú pháp tương tự như ví dụ của bạn, nhưng bạn có thể làm những gì bạn muốn làm, nội tuyến, khá dễ dàng với một CASEtuyên bố, như những người khác đã nói.

UDFthể là một cái gì đó như thế này:

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

... và bạn sẽ gọi nó như vậy ...

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

24
Tôi sẽ hỗ trợ bạn giải pháp, điều duy nhất tôi muốn thêm là hỗ trợ cho các giá trị NULL. Nếu bạn chỉ cần sửa đổi dòng cuối cùng: "return @ value2" để đọc là: "return isnull (@ val2, @ val1)" thì nếu một trong các giá trị là null, hàm sẽ trả về giá trị không null, nếu không nó sẽ hoạt động như bình thường
kristof

1
Thế còn các loại dữ liệu khác, ví dụ như tôi có cần phải viết một LowerIntegerArgument và một LowerDateTimeArgument và một LowerVarcharArgument và một ...?
onedaywhen ngày

9
điều này sẽ cực kỳ chậm, vì tất cả mọi thứ UDF vô hướng. Thay vào đó, hãy sử dụng UDF nội tuyến
AK

12
@xan Tôi không có manh mối gì trong đầu khi tôi thực sự hỏi câu hỏi đó. Không quá nhiều, rõ ràng. Dù sao cũng cảm ơn câu trả lời.
Thomas

13
@Thomas Hình ảnh meme bắt buộc (không có ý định xúc phạm bạn dưới bất kỳ hình thức nào!) Flickr.com/photos/16201371@N00/2375571206
xan

468

Nếu bạn đang sử dụng SQL Server 2008 (hoặc cao hơn), thì đây là giải pháp tốt hơn:

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

Tất cả tín dụng và phiếu bầu nên đi đến câu trả lời của Sven cho một câu hỏi liên quan, "SQL MAX của nhiều cột?"
Tôi nói đó là " câu trả lời tốt nhất " bởi vì:

  1. Nó không yêu cầu làm phức tạp mã của bạn với các thống kê CASE của UNION, PIVOT, UNPIVOT, UDF và điên cuồng.
  2. Nó không bị ảnh hưởng bởi vấn đề xử lý null, nó xử lý chúng tốt.
  3. Thật dễ dàng để trao đổi "MAX" với "MIN", "AVG" hoặc "SUM". Bạn có thể sử dụng bất kỳ hàm tổng hợp nào để tìm tổng hợp trên nhiều cột khác nhau.
  4. Bạn không bị giới hạn tên tôi đã sử dụng (tức là "AllPrices" và "Giá"). Bạn có thể chọn tên của riêng bạn để dễ đọc và dễ hiểu hơn cho anh chàng tiếp theo.
  5. Bạn có thể tìm thấy nhiều tập hợp bằng cách sử dụng các tệp_t_t của SQL Server 2008 như vậy:
    CHỌN MAX (a), MAX (b) TỪ (GIÁ TRỊ (1, 2), (3, 4), (5, 6), (7, 8), (9, 10)) NHƯ MyTable (a, b)

27
+1 chỉ trả lời không yêu cầu quyền truy cập để tạo thủ tục / hàm!
Alex

6
Chính xác là loại câu trả lời tôi đang tìm kiếm. Sử dụng các chức năng là chậm và điều này cũng sẽ hoạt động vào ngày, đó là những gì tôi cần.
Johann Strydom

3
+1 Hoạt động hoàn hảo, đặc biệt là hơn 2 cột được so sánh!
JanW

11
Điều này ít hiệu quả hơn so với giải pháp CASE WHEN chỉ cần tính toán vô hướng.
tekumara

5
Mặc dù cú pháp đơn giản hơn có thể không bao giờ có giá trị đánh hiệu năng khi xác định MAX của 2 giá trị, nó có thể là một vấn đề khác với nhiều giá trị hơn. Ngay cả khi nhận được MAX của 4 giá trị, các mệnh đề CASE trở nên dài, vụng về và dễ bị lỗi nếu được tạo bằng tay trong khi mệnh đề VALUES vẫn đơn giản và rõ ràng.
Typhlosaurus

221

Có thể được thực hiện trong một dòng:

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

Chỉnh sửa: Nếu bạn đang xử lý số lượng rất lớn, bạn sẽ phải chuyển đổi các biến giá trị thành bigint để tránh tràn số nguyên.


18
+1 Tôi tin rằng bạn đã cung cấp cách chính xác nhất. "CHỌN ((@ val1 + @ val2) + ABS (@ val1- @ val2)) / 2 là MAX_OF_TWO" Cũng nhớ, "CHỌN ((@ val1 + @ val2) - ABS (@ val1- @ val2)) / 2 là MIN_OF_TWO ".
tom

6
Cách này sẽ gây ra lỗi tràn nếu tổng lớn hơn có thể được lưu trữ trong một int: kê khai @ val1 int khai báo @ val2 int set @ val1 = 1500000000 set @ val2 = 1500000000 CHỌN 0,5 * ((@ val1 + @ val2) + ABS (@ val1 - @ val2)) - => lỗi tràn
AakashM

89
Đây là "mánh khóe" cực kỳ "bẩn". Khi lập trình mã của bạn phải thể hiện rõ ràng mục tiêu, tuy nhiên trong trường hợp của bạn, nó trông giống như mã được lấy từ cuộc thi obfuscation.
greenoldman

24
Nó có thể "bẩn", nhưng nó có thể là lựa chọn duy nhất cho cơ sở dữ liệu với các phương ngữ SQL đơn giản.
splattne

12
Tôi không đồng ý với marcias. Mã không nhất thiết phải tự thể hiện rõ ràng mục tiêu, miễn là các bình luận cho phép một người thực hiện nó. Nếu bạn đang thực hiện bất kỳ phương trình toán học phức tạp nào trong mã (hoặc bất cứ nơi nào), đôi khi thật khó để làm cho nó tự mô tả. Miễn là nó được chia thành các phần đơn giản hơn, dễ hiểu hơn thì đó là lập trình chính xác.
Cướp

127

Tôi không nghĩ vậy. Tôi muốn điều này vào ngày khác. Gần nhất tôi nhận được là:

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

4
Đây là phương pháp yêu thích của tôi. Bạn không có nguy cơ tràn, và nó ít khó hiểu hơn giải pháp của splattne (đó là btw tuyệt vời) và tôi không gặp khó khăn khi tạo UDF. trường hợp rất tiện dụng trong nhiều tình huống.
Lance Fisher

CHỌN o.OrderId, CASE KHI o.NegotiatedPrice> o.SuggestedPrice HOẶC o.SuggestedPrice IS NULL THEN ELSE o.NegotiatedPrice o.SuggestedPrice END TỪ tự o
mohghaderi

Khi thay vì "o.Negotiatedprice", bạn có một thuật ngữ như "(dateiff (day, convert (datetime, adr_ Unknown_since, 120), getdate ()) - 5) * 0.3" bạn phải lặp lại mã này. Bất kỳ thay đổi trong tương lai cho thuật ngữ phải được thực hiện hai lần. Hàm loại min (x, y, ...) sẽ đẹp hơn nhiều
Daniel

87

Tại sao không thử chức năng IIF (yêu cầu SQL Server 2012 trở lên)

IIF(a>b, a, b)

Đó là nó.

(Gợi ý: hãy cẩn thận về một trong hai null, vì kết quả a>bsẽ là sai bất cứ khi nào là null. Vì vậy, bsẽ là kết quả trong trường hợp này)


7
Nếu một trong các giá trị là NULL, kết quả sẽ luôn là giá trị thứ hai.
17:00

4
IIF () là đường cú pháp cho câu lệnh CASE. Nếu một trong hai giá trị của điều kiện CASE là NULL, kết quả sẽ là giá trị thứ hai (ELSE).
xxyzzy

@xxyzzy đó là vì NULL > 1234tuyên bố là sai
Xin

8
vì vậy IIF(a>b, a, COALESCE(b,a))để cung cấp giá trị khi chỉ có một tồn tại
mpag

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

Tôi cho giải pháp này là +1 vì nó phù hợp với DRY (không lặp lại chính mình) mà không cần phải viết UDF. Thật tuyệt vời nếu cả hai giá trị bạn cần kiểm tra đều là kết quả của các sql khác, ví dụ trong trường hợp của tôi, tôi muốn tìm lớn hơn 2 câu lệnh chọn (*).
MikeKulls

1
Tôi ghét rằng tôi phải dùng đến giải pháp này, nhưng chắc chắn đó là cách tốt nhất để thực hiện nó trong SQL Server cho đến khi họ thêm hỗ trợ riêng cho TUYỆT VỜI hoặc MAX trong dòng. Cảm ơn bạn đã đăng nó - +1 cho bạn!
SqlRyan

10

Các câu trả lời khác là tốt, nhưng nếu bạn phải lo lắng về việc có các giá trị NULL, bạn có thể muốn biến thể này:

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
ISNULL yêu cầu duy nhất là sau ELSE. So sánh ">" ban đầu sẽ trả về false và chuyển đến ELSE nếu một trong hai giá trị này là null.
Phil B

10

Trong SQL Server 2012 trở lên, bạn có thể sử dụng kết hợp IIFISNULL(hoặc COALESCE) để nhận tối đa 2 giá trị.
Ngay cả khi 1 trong số họ là NULL.

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

Hoặc nếu bạn muốn nó trả về 0 khi cả hai đều là NULL

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

Đoạn trích ví dụ:

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

Kết quả:

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

Nhưng nếu một người cần SUM nhiều giá trị?
Sau đó, tôi đề nghị CROSS ỨNG DỤNG để tổng hợp các GIÁ TRỊ.
Điều này cũng có lợi ích là điều này có thể tính toán những thứ khác cùng một lúc.

Thí dụ:

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

Truy vấn phụ có thể truy cập các cột từ truy vấn bên ngoài để bạn có thể sử dụng phương pháp này để sử dụng các tổng hợp như MAXtrên các cột. (Có lẽ hữu ích hơn khi có số lượng cột nhiều hơn tham gia)

;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

Đẹp! Nó vảy lên rất tốt.
greenoldman

+1 để hiển thị Tình yêu cho những người vẫn còn trên 2005. Tôi không biết làm thế nào tôi bỏ qua câu trả lời này. Dưới vỏ bọc, tôi tưởng tượng nó hoạt động tốt như những gì tôi đã đăng 2 năm sau. Nhìn lại, tôi nên nhận ra điều này và cập nhật câu trả lời của bạn để bao gồm cú pháp 2008 mới hơn vào thời điểm đó. Xin lỗi, ước gì tôi có thể chia sẻ quan điểm của mình với bạn bây giờ.
MikeTeeVee

@MikeTeeVee - Cảm ơn! Có dưới vỏ bọc kế hoạch sẽ giống nhau. Nhưng VALUEScú pháp đẹp hơn.
Martin Smith

6

Giới thiệu SQL Server 2012 IIF:

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

Xử lý NULL được khuyến nghị khi sử dụng IIF, bởi vì một NULLtrong hai phía của bạn boolean_expressionsẽ khiến IIFtrả lại false_value(trái ngược với NULL).


Giải pháp của bạn sẽ không xử lý tốt NULL khi giá trị khác âm, giá trị này sẽ trả về null
t-clausen.dk

5

Tôi sẽ đi với giải pháp được cung cấp bởi kcrumley Chỉ cần sửa đổi nó một chút để xử lý 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

EDIT Sửa đổi sau khi nhận xét từ Mark . Như ông đã chỉ ra một cách chính xác trong 3 logic có giá trị x> NULL hoặc x <NULL nên luôn trả về NULL. Nói cách khác kết quả không rõ.


1
Nulls rất quan trọng. Và điều quan trọng là phải xử lý chúng một cách nhất quán. Câu trả lời thích hợp duy nhất cho Is NULL> x là NULL.
Đánh dấu Brackett

Bạn nói đúng, tôi sẽ sửa đổi câu trả lời của mình để phản ánh điều đó, cảm ơn vì đã chỉ ra điều đó
kristof

Nếu chúng ta truyền int và NULL thì tôi nghĩ sẽ phổ biến hơn khi muốn trả về giá trị khác null, vì vậy hàm này đóng vai trò là sự kết hợp của Max (x, y) và ISNULL (x, y). Do đó, cá nhân tôi sẽ thay đổi dòng cuối cùng thành: return ISNULL (@ val1, @ val2) - có thể thừa nhận đó là những gì bạn phải bắt đầu với :)
redcalx

@ the-locster, xem bình luận của Mark
kristof

1
điều này sẽ cực kỳ chậm, vì tất cả mọi thứ UDF vô hướng. Thay vào đó, hãy sử dụng UDF nội tuyến
AK

4

Nó đơn giản như thế này:

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;

Xem @Neil nhận xét cho câu trả lời trước CHỌN dbo.InlineMax (CAST (0,5 AS FLOAT), 100) là sai.
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

Để biết cụ thể xin vui lòng tham khảo bài viết này: red-gate.com/simple-talk/sql/sql-training/...
Tom Arleth

2
Vui lòng không bao gồm thông tin cần thiết vào mã của bạn chỉ bằng một liên kết. Hãy tưởng tượng rằng liên kết này sẽ hết hạn vào một ngày và câu trả lời của bạn sẽ vô dụng sau đó. Vì vậy, hãy tiếp tục và thêm thông tin essentiell trực tiếp vào câu trả lời của bạn. Nhưng bạn vẫn có thể cung cấp liên kết đó dưới dạng nguồn tài nguyên để người khác tìm kiếm thêm thông tin.
L. Guthardt

3

Rất tiếc, tôi vừa đăng một bản dupe của câu hỏi này ...

Câu trả lời là, không có chức năng tích hợp như Greatest của Oracle , nhưng bạn có thể đạt được kết quả tương tự cho 2 cột với UDF, lưu ý, việc sử dụng sql_variant khá quan trọng ở đây.

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

mẹ con

Đăng câu trả lời này:

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
Lưu ý: việc triển khai chức năng TUYỆT VỜI nhất sẽ khớp với hành vi của nhà tiên tri trong 2 thông số, nếu bất kỳ thông số nào là null, nó sẽ trả về null
Sam Saffron

2
Bạn nên cẩn thận khi sử dụng sql_variant. Chức năng của bạn sẽ cho kết quả không mong muốn trong tình huống sau: CHỌN dbo.greatest (CAST (0,5 AS FLOAT), 100)
Neil

@Neil đã đúng (tôi đã học nó một cách khó khăn), bạn sẽ cải thiện chức năng này như thế nào để ngăn chặn loại vấn đề này?
Luca

3

Đây là một ví dụ điển hình nên xử lý null và sẽ hoạt động với các phiên bản cũ hơn của MSSQL. Điều này dựa trên hàm nội tuyến trong một trong những ví dụ phổ biến:

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

2

Tôi có thể sẽ không làm theo cách này, vì nó kém hiệu quả hơn các cấu trúc CASE đã được đề cập - trừ khi, có lẽ, bạn đã bao gồm các chỉ mục cho cả hai truy vấn. Dù bằng cách nào, đó là một kỹ thuật hữu ích cho các vấn đề tương tự:

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

Đối với câu trả lời ở trên liên quan đến số lượng lớn, bạn có thể thực hiện phép nhân trước khi cộng / trừ. Nó cồng kềnh hơn một chút nhưng không yêu cầu diễn viên. (Tôi không thể nói về tốc độ nhưng tôi cho rằng nó vẫn còn khá nhanh)

CHỌN 0,5 * ((@ val1 + @ val2) + ABS (@ val1 - @ val2))

Thay đổi

CHỌN @ val1 * 0,5 + @ val2 * 0,5 + ABS (@ val1 * 0,5 - @ val2 * 0,5)

ít nhất là một sự thay thế nếu bạn muốn tránh truyền.


2

Đây là phiên bản IIF có xử lý NULL (dựa trên câu trả lời của Xin):

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

Logic như sau, nếu một trong hai giá trị là NULL, trả về giá trị không phải là NULL (nếu cả hai đều là NULL, thì NULL được trả về). Nếu không thì trả lại cái lớn hơn.

Tương tự có thể được thực hiện cho MIN.

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

1

Bạn có thể làm một cái gì đó như thế này:

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

Ở dạng đơn giản nhất ...

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

Đối với SQL Server 2012:

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

1

Đây là câu trả lời của @Scott Langham với cách xử lý NULL đơn giản:

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;

Mặc dù sử dụng VALUESnội tuyến thú vị như vậy, tôi không chắc điều này đơn giản hơn CASEhay IFF. Tôi rất muốn xem hiệu suất của giải pháp này vượt trội so với các lựa chọn khác như thế nào
Chris Schaller

0

Mở rộng câu trả lời của Xin và giả sử loại giá trị so sánh là INT, phương pháp này cũng hoạt động:

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

Đây là một thử nghiệm đầy đủ với các giá trị mẫu:

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

Trong MemQuery, hãy làm như sau:

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

Trong Presto bạn có thể sử dụng

SELECT array_max(ARRAY[o.NegotiatedPrice, o.SuggestedPrice])
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.