source

SQL Server에는 Math와 같은 두 가지 값을 취하는 Max 함수가 있나요?최대 입력.인터넷?

ittop 2023. 4. 7. 21:55
반응형

SQL Server에는 Math와 같은 두 가지 값을 취하는 Max 함수가 있나요?최대 입력.인터넷?

다음과 같은 질문을 쓰고 싶습니다.

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

으로 안 돼MAX★★★★★★★★★★★★★★★★★?집약함수이기 때문에 단일 파라미터를 상정하고 모든 행의 MAX를 반환합니다.

내 방식대로 할 줄 아는 사람 있어?

SQL Server 2008(또는 그 이후)을 사용하는 경우에는 다음과 같은 솔루션이 적합합니다.

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

모든 신용과 투표는 관련된 질문인 "SQL MAX of multiple columns?"에 대한 Sven의 답변으로 돌아갑니다.
제가 "최적의 답변"이라고 말하는 이유는 다음과 같습니다.

  1. UNION, PIVOT, UDF 및 crazy-long CASE 문장과 코드를 복잡하게 만들 필요가 없습니다.
  2. Null을 처리하는 문제로 고민하는 것이 아니라 잘 처리할 수 있습니다.
  3. 「MAX」를 「MIN」, 「AVG」, 또는 「SUM」으로 간단하게 교환할 수 있습니다.집약 함수를 사용하면, 다양한 열의 집계를 찾을 수 있습니다.
  4. 제가 사용한 이름('All Price' 및 'Price' 등)에만 국한되지 않습니다.다음 사람이 쉽게 읽고 이해할 수 있도록 자신의 이름을 선택할 수 있습니다.
  5. SQL Server 2008 derived_tables를 사용하면 다음과 같이 여러 애그리게이트를 찾을 수 있습니다.
    (1, 2 (3, (5 (7 ( MyTable MAX(a), MAX(b) FROM(1, 2), (3, 6), (7, 8), (9), (10)을 선택합니다.

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

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

편집: 매우 큰 숫자를 다루는 경우 정수 오버플로를 방지하기 위해 값 변수를 bigint로 변환해야 합니다.

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

난 그렇게 생각 안 해.요전에는 이걸 원했어요.내가 가장 근접한 건

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)

바로 그겁니다.

( 어느쪽이든 해 주세요.a ★★★★★★★★★★★★★★★★★」bnull " "의 a>b거짓이 될 것이다. ★★★★★★★★★★★★★★★★★.b 중 가 반환 입니다.null 시스템 ('null'은 권장되지 않습니다.)

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

Server 2012를 할 수 .IIF ★★★★★★★★★★★★★★★★★」ISNULL (오류)COALESCE2번입니다.
중 NULL인 에도 NULL입니다.

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

하만 최최 ?가 ?? ???
그리고 나는 가치의 집계에 크로스 적용을 제안합니다.

예:

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

이것은 다른 것들을 동시에 계산할 수 있다는 추가적인 이점이 있습니다.

이거 먹어봐.3개 이상의 값을 처리할 수 있습니다.

SELECT Max(v) FROM (VALUES (1), (2), (3)) AS value(v)

다른 답변도 좋지만 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

네, 있습니다.

T-SQL(SQL Server 2022(16.x))은 이제 GREATE/LEST 기능을 지원합니다.

비집약 함수로서의 MAX/MIN

이제 Azure SQL 데이터베이스 및 SQL Managed Instance에 대해 라이브입니다.다음 버전의 SQL Server로 롤백됩니다.


논리 함수 - GREATE (Transact-SQL)

이 함수는 하나 이상의 식 목록에서 최대값을 반환합니다.

GREATEST ( expression1 [ ,...expressionN ] ) 

이 경우:

SELECT o.OrderId, GREATEST(o.NegotiatedPrice, o.SuggestedPrice)
FROM [Order] o;

db <> 데모 표시

하위 쿼리는 외부 쿼리에서 열에 액세스할 수 있으므로 이 방법을 사용하여 다음과 같은 집계를 사용할 수 있습니다.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
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

kcrumley가 제공하는 솔루션을 사용합니다.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을 반환해야 합니다.즉, 알 수 없는 결과입니다.

SQL Server 2012는 다음과 같이 도입되었습니다.

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

의 취급은, 「NULL」을 사용하는 합니다.IIF「」이 있기 때문에NULLboolean_expression이 되다IIFfalse_value)NULL

이미 언급한 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

이런, 방금 이 질문을 중복해서 올렸는데...

정답은 Oracle의 Greatest와 같은 함수는 없지만 UDF를 사용하여 두 열에 대해 유사한 결과를 얻을 수 있다는 것입니다. 여기서 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

다음과 같이 심플합니다.

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;

다음과 같은 작업을 수행할 수 있습니다.

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

큰 숫자에 대한 위의 답은 덧셈/감산 전에 곱셈을 할 수 있습니다.조금 더 부피가 크지만 깁스는 필요 없습니다.(속도는 말할 수 없지만, 아직 꽤 빠르다고 생각합니다.)

선택 0.5 * ((@val1 + @val2) + ABS(@val1 - @val2))

변경 사항

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

캐스팅을 피하고 싶다면 적어도 대안으로 삼아야 한다.

다음은 null을 처리하고 이전 버전의 MSSQL에서 작동하는 예입니다.이것은 일반적인 예 중 하나1개의 인라인 기능에 근거하고 있습니다.

case
  when a >= b then a
  else isnull(b,a)
end
 -- 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;
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

@Scott Langham의 간단한 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]

가장 간단한 형태로...

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

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

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;

언급URL : https://stackoverflow.com/questions/124417/is-there-a-max-function-in-sql-server-that-takes-two-values-like-math-max-in-ne

반응형