SQL Server中是否有接受两个值(如.NET中的Math.Max)的Max函数?
我想写一个如下的查询:SQL Server中是否有接受两个值(如.NET中的Math.Max)的Max函数?,sql,sql-server,max,Sql,Sql Server,Max,我想写一个如下的查询: SELECT o.OrderId, MAX(o.NegotiatedPrice, o.SuggestedPrice) FROM Order o select case when o.NegotiatedPrice > o.SuggestedPrice then o.NegotiatedPrice else o.SuggestedPrice end create function dbo.InlineMax(@val1 int, @val2 int) retur
SELECT o.OrderId, MAX(o.NegotiatedPrice, o.SuggestedPrice)
FROM Order o
select case when o.NegotiatedPrice > o.SuggestedPrice
then o.NegotiatedPrice
else o.SuggestedPrice
end
create function dbo.InlineMax(@val1 int, @val2 int)
returns int
as
begin
if @val1 > @val2
return @val1
return isnull(@val2,@val1)
end
但是MAX
函数不是这样工作的,对吗?它是一个聚合函数,因此需要一个参数,然后返回所有行的最大值
有人知道我怎么做吗?我不这么认为。前几天我想要这个。我得到的最接近的结果是:
SELECT
o.OrderId,
CASE WHEN o.NegotiatedPrice > o.SuggestedPrice THEN o.NegotiatedPrice
ELSE o.SuggestedPrice
END
FROM Order o
您可以这样做:
SELECT o.OrderId, MAX(o.NegotiatedPrice, o.SuggestedPrice)
FROM Order o
select case when o.NegotiatedPrice > o.SuggestedPrice
then o.NegotiatedPrice
else o.SuggestedPrice
end
create function dbo.InlineMax(@val1 int, @val2 int)
returns int
as
begin
if @val1 > @val2
return @val1
return isnull(@val2,@val1)
end
我可能不会这样做,因为它比前面提到的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
如果希望语法与示例相似,则需要创建一个
用户定义函数
,但是否可以像其他人所说的那样,通过CASE
语句内联地完成您想要做的事情
UDF
可以是这样的:
SELECT o.OrderId, MAX(o.NegotiatedPrice, o.SuggestedPrice)
FROM Order o
select case when o.NegotiatedPrice > o.SuggestedPrice
then o.NegotiatedPrice
else o.SuggestedPrice
end
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
其他答案很好,但如果您不得不担心空值,您可能需要以下变体:
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
我会同意 只需稍微修改它以处理空值
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
创建函数dbo.HigherArgumentOrNull(@val1 int,@val2 int)
返回整数
作为
开始
如果@val1>=@val2
返回@val1
如果@val1<@val2
返回@val2
小风一吹
结束
编辑
修改后的评论。正如他在三值逻辑中正确指出的那样,x>NULL或xcreate 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
可以在一行中完成:
-- the following expression calculates ==> max(@val1, @val2)
SELECT 0.5 * ((@val1 + @val2) + ABS(@val1 - @val2))
编辑:如果处理的是非常大的数字,则必须将值变量转换为bigint,以避免整数溢出 对于上面关于大数字的答案,您可以在加法/减法之前进行乘法。它有点笨重,但不需要石膏。(我不能说速度有多快,但我认为速度还是很快的) 选择0.5*(@val1+@val2)+ 绝对值(@val1-@val2)) 更改为 选择@val1*0.5+@val2*0.5+ 绝对值(@val1*0.5-@val2*0.5)
如果你想避免铸造,至少有一种选择 子查询可以从外部查询访问列,因此您可以使用来跨列使用聚合,例如
MAX
。(但当涉及更多列时,可能更有用)
以最简单的形式
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 2008(或更高版本),那么这是更好的解决方案:
SELECT o.OrderId,
(SELECT MAX(Price)
FROM (VALUES (o.NegotiatedPrice),(o.SuggestedPrice)) AS AllPrices(Price))
FROM Order o
所有的信用和选票都应该交给
我之所以说这是“最佳答案”,是因为:
从(值(1,2)、(3,4)、(5,6)、(7,8)、(9,10))中选择MAX(a)、MAX(b)作为MyTable(a、b)
就这么简单:
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;
SQL Server 2012已推出: 建议在使用
IIF
时处理空值,因为boolean\u表达式两侧的NULL
将导致IIF
返回false\u值(与NULL
相反) 对于SQL Server 2012:
SELECT
o.OrderId,
IIF( o.NegotiatedPrice >= o.SuggestedPrice,
o.NegotiatedPrice,
ISNULL(o.SuggestedPrice, o.NegiatedPrice)
)
FROM
Order o
为什么不试试IIF函数(需要SQL Server 2012及更高版本)
就这样
(提示:请注意其中一个将为null
,因为a>b
的结果在任何一个为null时都将为false。因此在这种情况下,b
将是结果)下面是一个应处理null的案例示例,它将用于MSSQL的旧版本。这是基于一个流行示例中的内联函数:
case
when a >= b then a
else isnull(b,a)
end
下面是@Scott Langham对简单空处理的回答:
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
以下是一个带有空处理的IIF版本(基于Xin的答案):
逻辑如下,如果其中一个值为NULL,则返回一个不为NULL的值(如果两者都为NULL,则返回NULL)。否则返回较大的一个
同样的方法也适用于MIN
IIF(a IS NULL OR b IS NULL, ISNULL(a,b), IIF(a < b, a, b))
IIF(a为NULL或b为NULL,ISNULL(a,b),IIF(a
选择订单ID(
从中选择最大值([价格])(
选择NegotiatedPrice[价格]
联合所有
选择建议价格
)p
)从[命令]
扩展Xin的答案并假设比较值类型为INT,此方法也有效:
SELECT IIF(ISNULL(@A, -2147483648) > ISNULL(@B, -2147483648), @A, @B)
这是一个具有示例值的完整测试:
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
在SQL Server 2012或更高版本中,您可以结合使用IIF
和ISNULL
(或COALESCE
)来获得最多2个值。
即使其中1个为空
IIF(col1 >= col2, col1, ISNULL(col2, col1))
或者,如果希望在两者都为NULL时返回0
IIF(col1 >= col2, col1, COALESCE(col2, col1, 0))
示例代码段:
结果:
但是如果一个人需要最多多列?
然后我建议交叉应用于值的聚合
例如:
SELECT t.*
, ca.[Maximum]
, ca.[Minimum], ca.[Total], ca.[Average]
FROM SomeTable t
CROSS APPLY (
SELECT
MAX(v.col) AS [Maximum],
MIN(v.col) AS [Minimum],
SUM(v.col) AS [Total],
AVG(v.col) AS [Average]
FROM (VALUES (t.Col1), (t.Col2), (t.Col3), (t.Col4)) v(col)
) ca
这还有一个额外的好处,那就是它可以同时计算其他内容。在MemSQL中执行以下操作:
-- 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;
试试这个。它可以处理2个以上的值
SELECT Max(v) FROM (VALUES (1), (2), (3)) AS value(v)
是的,有。
T-SQL现在支持最大/最小函数:
这是Azure SQL数据库和SQL托管实例的实时版本。它将应用到SQL Server的下一个版本中
-- 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
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
SELECT t.*
, ca.[Maximum]
, ca.[Minimum], ca.[Total], ca.[Average]
FROM SomeTable t
CROSS APPLY (
SELECT
MAX(v.col) AS [Maximum],
MIN(v.col) AS [Minimum],
SUM(v.col) AS [Total],
AVG(v.col) AS [Average]
FROM (VALUES (t.Col1), (t.Col2), (t.Col3), (t.Col4)) v(col)
) ca
-- 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;
SELECT Max(v) FROM (VALUES (1), (2), (3)) AS value(v)
GREATEST ( expression1 [ ,...expressionN ] )
SELECT o.OrderId, GREATEST(o.NegotiatedPrice, o.SuggestedPrice)
FROM Order o