다음과 같은 쿼리를 작성하고 싶습니다.
SELECT o.OrderId, MAX(o.NegotiatedPrice, o.SuggestedPrice)
FROM Order o
그러나 이것은 MAX
기능이 작동 하는 방식이 아닙니다 . 집계 함수이므로 단일 매개 변수를 예상 한 다음 모든 행의 MAX를 리턴합니다.
누구든지 내 방식대로하는 법을 알고 있습니까?
다음과 같은 쿼리를 작성하고 싶습니다.
SELECT o.OrderId, MAX(o.NegotiatedPrice, o.SuggestedPrice)
FROM Order o
그러나 이것은 MAX
기능이 작동 하는 방식이 아닙니다 . 집계 함수이므로 단일 매개 변수를 예상 한 다음 모든 행의 MAX를 리턴합니다.
누구든지 내 방식대로하는 법을 알고 있습니까?
답변:
User-Defined Function
예제와 비슷한 구문을 원한다면 if 를 작성해야 하지만 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 이상을 사용하는 경우 이것이 더 나은 솔루션입니다.
SELECT o.OrderId,
(SELECT MAX(Price)
FROM (VALUES (o.NegotiatedPrice),(o.SuggestedPrice)) AS AllPrices(Price))
FROM Order o
모든 크레딧과 투표는 관련 질문 인 "여러 열의 SQL MAX?"에 대한 Sven의 답변으로
가야합니다.
" 최고의 답변 " 이라고 말합니다 .
한 줄로 할 수 있습니다 :
-- 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 일 때마다 null
결과 a>b
가 false이므로주의하십시오. b
이 경우 결과가됩니다)
NULL
인 경우 결과는 항상 두 번째입니다.
NULL > 1234
진술이 거짓 이기 때문에
IIF(a>b, a, COALESCE(b,a))
하나가 존재하는 경우 값을 제공합니다
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
SQL Server 2012 이상에서는 IIF
and ISNULL
(또는 COALESCE
) 조합을 사용 하여 최대 2 개의 값을 얻을 수 있습니다.
그중 하나가 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
그러나 여러 값을 합산해야한다면?
그런 다음 CROSS APPLY를 값 집계에 적용하는 것이 좋습니다.
이것은 또한 다른 것들을 동시에 계산할 수 있다는 이점이 있습니다.
예:
SELECT t.*
, ca.[Total]
, ca.[Maximum]
, ca.[Minimum]
, ca.[Average]
FROM SomeTable t
CROSS APPLY (
SELECT
SUM(v.col) AS [Total],
MIN(v.col) AS [Minimum],
MAX(v.col) AS [Maximum],
AVG(v.col) AS [Average]
FROM (VALUES (t.Col1), (t.Col2), (t.Col3), (t.Col4)) v(col)
) ca
하위 쿼리는 외부 쿼리에서 열에 액세스 할 수 있으므로이 방법 을 사용 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
VALUES
구문이 더 좋습니다.
SQL Server 2012 소개 IIF
:
SELECT
o.OrderId,
IIF( ISNULL( o.NegotiatedPrice, 0 ) > ISNULL( o.SuggestedPrice, 0 ),
o.NegotiatedPrice,
o.SuggestedPrice
)
FROM
Order o
사용할 때 권장 NULL을 처리 IIF
때문에, NULL
당신의 양쪽에 boolean_expression
의지 원인이 IIF
을 반환 false_value
(반대 NULL
).
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
EDIT Mark의 주석 이후 수정되었습니다 . 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;
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
죄송합니다. 이 질문에 대한 내용을 게시했습니다 .
대답은 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
간단한 NULL 처리를 통한 @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
-- 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;
VALUES
인라인을 흥미롭게 사용하지만 이것이 CASE
또는 보다 단순하다는 것을 확신하지 못합니다 IFF
.
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
GREATEST
함수 로 구현됩니다 . SQLite는MAX
집계 에서 여러 열을 허용하여 지원을 에뮬레이트합니다 .