Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-cloud-platform/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server中是否有接受两个值(如.NET中的Math.Max)的Max函数?_Sql_Sql Server_Max - Fatal编程技术网

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或x哦,我刚刚发布了一个

答案是,没有类似的内置函数,但是您可以使用UDF为2列实现类似的结果,注意,在这里使用sql_变量非常重要

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

可以在一行中完成:

-- 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
所有的信用和选票都应该交给
我之所以说这是“最佳答案”,是因为:

  • 它不需要将代码与UNION的、PIVOT的、, UNPIVOT's、UDF's和疯狂的长病例陈述
  • 它没有处理空值的问题,它处理得很好
  • 用“最小”、“平均值”或“总和”替换“最大值”很容易。您可以使用任何聚合函数来查找多个不同列上的聚合
  • 您不限于我使用的名称(即“AllPrices”和“Price”)。你可以选择自己的名字,让下一个男人更容易阅读和理解
  • 您可以使用SQL Server 2008找到多个聚合,如下所示:
    从(值(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