이 있 Max 함수에서 SQL 서버는 두 값이 다음과 같 수학이다.최대습니다.NET?

StackOverflow https://stackoverflow.com/questions/124417

  •  02-07-2019
  •  | 
  •  

문제

내가 원하는 쿼리를 작성하려면 다음과 같다:

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

그러나 이것은 어떻게 MAX 기능,right?그것은 집계 기능으로 예상 하나의 매개 변수를 반환하기 전에 최대의 모든 행이 있습니다.

누군가하는 방법을 알고 그것을 할 방법이 있을까?

도움이 되었습니까?

해결책

당신은 만들어야합니다 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 Server2008(또는 그 이상),이것은 더 나은 솔루션:

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

모든 신고 투표에 가야한다 Sven 의 대답은 관련된 질문에"SQL 최대의 여러 열?"
내가 말한 그것은"최고의 응답"기:

  1. 그것은 필요하지 않 복잡는 코드로 연합 의,피벗의 피벗 해제의 UDF 의,그리고 미친 긴 경우 문에서도.
  2. 그렇지 않을 괴롭힌 문제를 처리하는 null,그것은 처리됩니다.
  3. 그것은 쉽게 교체할"MAX""분","AVG",또는"합".당신이 사용할 수 있는 집합 기능을 찾기 위해 집계를 통해 다른 많은 열이 있습니다.
  4. 당신이 제한되지 않는 이름을 내가 사용하는(i.e"AllPrices"및"가격").당신이 선택할 수 있습니다 당신의 자신의 이름을 보다 쉽게 읽고 이해하기 위해 다음 사람입니다.
  5. 을 찾을 수 있습 여러 집계를 사용하여 SQL Server2008 의 derived_tables 그래서 다음과 같:
    선택 MAX(a),MAX(b)(값(1, 2), (3, 4), (5, 6), (7, 8), (9, 10) ) 로됩니다.(a,b)

한 줄로 수행 할 수 있습니다.

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

편집하다: 매우 많은 숫자를 다루는 경우 정수 오버플로를 피하기 위해 값 변수를 Bigint로 변환해야합니다.

나는 그렇게 생각하지 않습니다. 나는 다른 날 이것을 원했다. 내가 얻은 가장 가까운 것은 :

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

시도해 보지 않겠습니까? iif 기능 (SQL Server 2012 이상 필요)

IIF(a>b, a, b)

그게 다야.

(힌트 : 어느 쪽이든주의하십시오 null, 결과 이후 a>b 둘 중 하나가 널이 될 때마다 거짓이됩니다. 그래서 b 이 경우 결과가 될 것입니다)

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

다른 답변은 좋지만 널 값이 걱정된다면이 변형을 원할 수 있습니다.

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, a NULL 당신의 양쪽에 boolean_expression 원인이됩니다 IIF 반환하려면 false_value (반대로 NULL).

나는 제공된 솔루션과 함께 갈 것입니다 Kcrumley널을 다루기 위해 약간 수정하십시오

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;

죄송합니다. 방금 게시했습니다 이 질문의 속임수...

대답은 오라클은 가장 위대한 것입니다, 그러나 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

다음은 널을 처리해야하며 이전 버전의 MSSQL에서 작동하는 사례 예입니다. 이것은 인기있는 예 중 하나의 인라인 함수를 기반으로합니다.

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

이미 언급 된 사례 구성보다 효율적이지 않기 때문에 이런 식으로하지 않을 것입니다. 어느 쪽이든, 그것은 비슷한 문제에 대한 유용한 기술입니다.

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

다음은 NULL 처리 기능이있는 IIF 버전입니다 (Xin의 답변 기반).

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

논리는 다음과 같습니다. 값 중 하나가 NULL이면 NULL이 아닌 값을 반환합니다 (둘 다 NULL이면 NULL이 반환됩니다). 그렇지 않으면 더 큰 것을 반환하십시오.

최소에 대해서도 마찬가지입니다.

IIF(a IS NULL OR b IS NULL, ISNULL(a,b), IIF(a < b, a, b))
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

당신은 다음과 같은 일을 할 수 있습니다 :

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

많은 숫자와 관련하여 위의 답변은 첨가/뺄셈 전에 곱셈을 할 수 있습니다. 조금 부러 지지만 캐스트가 필요하지 않습니다. (나는 속도를 말할 수 없지만 여전히 꽤 빠르다고 생각합니다)

0.5 * (( @val1 + @val2) + abs ( @val1- @val2)를 선택하십시오.

변경

@val1*0.5 + @val2*0.5 + abs ( @val1*0.5- @val2*0.5)를 선택하십시오.

캐스팅을 피하려면 대안입니다.

가장 간단한 형태로 ...

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

SQL Server 2012 이상에서는 조합을 사용할 수 있습니다. IIF 그리고 ISNULL (또는 COALESCE) 최대 2 값을 얻습니다.
그들 중 하나가 널이라도.

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

또는 둘 다 NULL 일 때 0을 반환하기를 원한다면

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

예제 스 니펫 :

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

다음은 간단한 널 처리로 @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
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])
 -- 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;

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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top