在SQL Server中是否有一个Max函数,它在.NET中有两个值,如Math.Max?

我想写一个这样的查询:

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

但这不是MAX函数的工作原理,对吗? 这是一个聚合函数,所以它需要一个参数,然后返回所有行的最大值。

有谁知道如何做到这一点我的方式?

如果你想使用类似于你的例子的语法,你需要创build一个User-Defined Function ,但是你可以像其他人所说的那样,用CASE语句很容易地进行内联操作。

UDF可能是这样的:

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

…你会这样称呼它…

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

如果您使用SQL Server 2008(或更高版本),那么这是更好的解决scheme:

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

所有的信用和投票都应该交给Sven对相关问题“多个列的SQL MAX?”的回答。
我说这是“ 最好的答案 ”,因为:

  1. 它不需要使用UNION,PIVOT,UNPIVOT,UDF和疯狂的CASE语句使代码复杂化。
  2. 它不是处理空值的问题,它处理它们就好了。
  3. 用“MIN”,“AVG”或“SUM”replace“MAX”是很容易的。 您可以使用任何聚合函数来查找多个不同列上的聚合。
  4. 您不仅限于我使用的名称(即“AllPrices”和“Price”)。 你可以select自己的名字,以便阅读和理解下一个家伙。
  5. 您可以使用SQL Server 2008的derived_tablesfind多个聚合, 如下所示:
    (1,2),(3,4),(5,6),(7,8),(9,10)

可以在一行中完成:

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

编辑: 如果你处理非常大的数字,你将不得不将值variables转换为bigint,以避免整数溢出。

我不这么认为。 我有一天想要这个。 我得到的最接近的是:

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

为什么不尝试IIFfunction(需要SQL Server 2012及更高版本)

 IIF(a>b, a, b) 

而已。

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

其他答案是好的,但是如果你不得不担心有NULL值,你可能想要这个变种:

 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 

子查询可以访问外部查询中的列,以便您可以使用此方法在列之间使用MAX等聚合。 (当涉及更多的列时可能会更有用)

 ;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 

SQL Server 2012引入了IIF

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

在使用IIF时build议使用NULL ,因为boolean_expression两边的NULL将导致IIF返回false_value (而不是NULL )。

我会去与kcrumley提供的解决scheme只是稍微修改它来处理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 

编辑修改后,从马克评论。 正如他正确地指出,3值逻辑x> NULL或x <NULL应始终返回NULL。 换句话说,未知的结果。

其如此简单:

 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; 

哎呀,我刚发布了这个问题

答案是,没有像Oracle's Greatest那样的内置函数,但是可以用UDF实现2列的类似结果,请注意,在这里使用sql_variant非常重要。

 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 

克里斯托夫

发表了这个答案:

 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 

我可能不会这样做,因为它比已经提到的CASE结构效率更低 – 除非你可能覆盖了两个查询的索引。 无论哪种方式,这是一个类似的问题有用的技术:

 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 

你可以做这样的事情:

 select case when o.NegotiatedPrice > o.SuggestedPrice then o.NegotiatedPrice else o.SuggestedPrice end 
 SELECT o.OrderID CASE WHEN o.NegotiatedPrice > o.SuggestedPrice THEN o.NegotiatedPrice ELSE o.SuggestedPrice END AS Price 
 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 

对于上面关于大数的答案,可以在加/减之前进行乘法运算。 这有点笨重,但不需要投射。 (我不能说速度,但我认为它仍然非常快)

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

更改

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

如果你想避免施放,至less可以select一个select。

最简单的forms

 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 

对于SQL Server 2012:

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

这里是一个应该处理空值的例子,并且可以和旧版本的MSSQL一起工作。 这是基于一个stream行示例中的内联函数:

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

@Scott朗廷的答案是简单的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 

这是一个带有NULL处理的IIF版本(根据Xin的回答):

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

逻辑如下,如果其中任何一个值为NULL,则返回不为NULL的值(如果两者均为NULL,则返回NULL)。 否则返回更大的一个。

MIN可以做同样的事情。

 IIF(a IS NULL OR b IS NULL, ISNULL(a,b), IIF(a < b, a, b)) 
 select OrderId, ( select max([Price]) from ( select NegotiatedPrice [Price] union all select SuggestedPrice ) p ) from [Order] 

在Presto你可以使用使用

 SELECT array_max(ARRAY[o.NegotiatedPrice, o.SuggestedPrice])