Я хочу написать такой запрос:
SELECT o.OrderId, MAX(o.NegotiatedPrice, o.SuggestedPrice)
FROM Order o
Но функция MAX работает не так, верно? Это агрегатная функция, поэтому она ожидает один параметр, а затем возвращает MAX всех строк.
Кто-нибудь знает, как это сделать по-моему?
Возможный дубликат stackoverflow.com/questions/71022/sql-max-of-multiple-column s
При поиске решения для max (a, b) ниже помните о том, хотите ли вы, чтобы синтаксис или вычисление для «a» и / или «b» повторялись. Т.е. если «b» получено из сложных вычислений с использованием большого количества синтаксиса, тогда вы можете предпочесть решение, в котором «b» появляется только один раз. Например. решение «IIF (a> b, a, b)» означает повторение «b», что может быть синтаксически некрасивым, однако следующее решение означает, что «b» (и «a») появляются только один раз: SELECT MAX (VALUE) FROM (ВЫБЕРИТЕ a КАК ЗНАЧЕНИЕ СОЕДИНЕНИЕ ВЫБРАТЬ b КАК ЗНАЧЕНИЕ) КАК T1


Я так не думаю. Я хотел это на днях. Ближайшее, что у меня получилось, было:
SELECT
o.OrderId,
CASE WHEN o.NegotiatedPrice > o.SuggestedPrice THEN o.NegotiatedPrice
ELSE o.SuggestedPrice
END
FROM Order o
Это мой любимый метод. Вы не рискуете переполнением, и это менее загадочно, чем решение splattne (что, кстати, круто), и у меня нет проблем с созданием UDF. чехол очень удобен во многих ситуациях.
ВЫБЕРИТЕ o.OrderId, СЛУЧАЙ, КОГДА o.NegotiatedPrice> o.SuggestedPrice ИЛИ o.SuggestedPrice IS NULL, ТО o.NegotiatedPrice ELSE o.SuggestedPrice END FROM Order o
Когда вместо «o.NegotiatedPrice» используется термин «(dateiff (day, convert (datetime, adr_known_since, 120), getdate ()) - 5) * 0.3», вам необходимо повторить этот код. Любые будущие изменения срока необходимо делать дважды. Функция типа min (x, y, ...) была бы намного лучше
Вы можете сделать что-то вроде этого:
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
иначе isnull (oSuggestedPrice, o, NegotiatedPrice)
Я бы, вероятно, не стал делать это таким образом, поскольку он менее эффективен, чем уже упомянутые конструкции 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
Вам нужно будет создать 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
Я бы поддержал ваше решение, единственное, что я бы добавил, - это поддержка значений NULL. Если вы просто измените последнюю строку: «return @ value2» на «return isnull (@ val2, @ val1)», тогда, если одно из значений равно null, функция вернет ненулевое значение, в противном случае она будет работать как обычный
А как насчет других типов данных, например мне нужно написать HigherIntegerArgument и HigherDateTimeArgument и HigherVarcharArgument и ...?
это будет невероятно медленно, как и все скалярные UDF. Вместо этого используйте встроенные UDF
Можно ли сделать что-то подобное, чтобы получить наименьшее из двух значений?
@xan Я понятия не имею, что пришло мне в голову, когда я на самом деле задал этот вопрос. Очевидно, не слишком много. В любом случае спасибо за ответ.
@Thomas Не беспокойтесь - я тоже время от времени задавал такие же вопросы. Иногда мозг просто слишком много думает ...
@Thomas Обязательное изображение мема (ни в коем случае не в оскорбление!) flickr.com/photos/16201371@N00/2375571206
Это решение имеет преимущество работы с любым типом данных, для которого определен >.
Обратите внимание, что отредактированное решение обрабатывает значения NULL, такие как Max (), по запросу (Max возвращает наибольшее значение, отличное от NULL), но не работает так же, как простые сравнения> (которые возвращают NULL, если любой из аргументов имеет значение NULL). При использовании в другом контексте это может привести к потенциально противоречивым результатам, например к утверждению, что -999999999 больше нуля. Я переименовал функцию, чтобы она больше не подразумевала, что она действует как «больше чем».
Этот ответ не работает, если разработчик, пишущий запрос, не имеет разрешения на создание пользовательских функций и не может убедить администраторов баз данных сделать это. Я предпочитаю ответы Д. Несмита и Марка Брэкетта. Хотя изменение ISNULL на COALESCE сделало бы ответ Д. Несмита более переносимым.
Другие ответы хороши, но если вам нужно беспокоиться о значениях 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
Требуется только ISNULL после ELSE. Первоначальное сравнение ">" вернет false и перейдет к ELSE, если какое-либо из значений уже равно нулю.
Я бы пошел с решением, предоставленным Крамли Просто немного измените его, чтобы обрабатывать 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
РЕДАКТИРОВАТЬ Изменено после комментария отметка. Как он правильно указал в трехзначной логике, x> NULL или x <NULL всегда должны возвращать NULL. Другими словами неизвестный результат.
Нули важны. И важно обращаться с ними последовательно. Единственный правильный ответ на Is NULL> x - NULL.
Вы правы, я изменю свой ответ, чтобы отразить это, спасибо, что указали на это
Если мы передадим int и NULL, тогда, я думаю, более распространено возвращение ненулевого значения, поэтому функция действует как комбинация Max (x, y) и ISNULL (x, y). Следовательно, я лично изменил бы последнюю строку на: return ISNULL (@ val1, @ val2) - что, по общему признанию, вероятно, то, с чего вам нужно было начать :)
@ the-locster, см. комментарий Марка
@ the-lobster, я согласен, что это более распространено, но см. комментарий Марка, значения NULL важны, и, как он указывает, «Единственный правильный ответ на Is NULL> x is NULL»
это будет невероятно медленно, как и все скалярные UDF. Вместо этого используйте встроенные UDF
Ой, я только что отправил дурак на этот вопрос ...
Ответ: нет встроенной функции, такой как Величайший Оракул, но вы можете добиться аналогичного результата для двух столбцов с помощью 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
Примечание: реализация функции GREATEST будет соответствовать поведению оракула для 2 параметров, если какой-либо параметр равен null, он вернет null
Будьте осторожны при использовании sql_variant. Ваша функция выдаст неожиданный результат в следующей ситуации: SELECT dbo.greatest (CAST (0.5 AS FLOAT), 100)
@ Нил прав (я усвоил это на собственном горьком опыте), как бы вы улучшили эту функцию, чтобы предотвратить подобные проблемы?
Можно сделать одной строкой:
-- the following expression calculates ==> max(@val1, @val2)
SELECT 0.5 * ((@val1 + @val2) + ABS(@val1 - @val2))
Редактировать:Если вы имеете дело с очень большими числами, вам придется преобразовать переменные значения в bigint, чтобы избежать целочисленного переполнения.
+1 Я считаю, что вы предоставили самый правильный способ. «SELECT ((@ val1 + @ val2) + ABS (@ val1- @ val2)) / 2 as MAX_OF_TWO» Также помните, «SELECT ((@ val1 + @ val2) - ABS (@ val1- @ val2)) / 2 как MIN_OF_TWO ".
Этот способ выдаст ошибку переполнения, если сумма больше, чем может быть сохранена в int: declare @ val1 int declare @ val2 int set @ val1 = 1500000000 set @ val2 = 1500000000 SELECT 0.5 * ((@ val1 + @ val2) + ABS (@ val1 - @ val2)) - => ошибка переполнения
Я такого раньше не видел. Гений.
Это крайне «грязный» «трюк». При программировании ваш код должен явно выражать цель, однако в вашем случае он выглядит как код, взятый из конкурса обфускации.
Он может быть «грязным», но это может быть единственный вариант для баз данных с простыми диалектами SQL.
Я не согласен с марсиасом. Код не обязательно сам по себе должен явно выражать цель, если комментарии позволяют решить ее. Если вы выполняете какие-либо сложные математические уравнения в коде (или где-то еще), иногда бывает сложно сделать его информативным. Пока он разбит на более простые и понятные части, это правильное программирование.
Изящный математический трюк, но меня раздражает идея выполнять арифметические операции с плавающей запятой, чтобы получить максимум два целых числа.
@King, это не с плавающей точкой, скажем, если вы замените * 0.5 на div 2, это снова целочисленная математика. Это также будет очень хорошо работать в другом коде, потому что вы избегаете перехода «если-то» и, следовательно, неверного предсказания ветви (очевидно, за счет более длинного критического пути).
Это будет работать для целых чисел и т. д., Но не для других типов данных, таких как datetime (что было моим конкретным вариантом использования - создайте столбец в наборе результатов, который в каждой строке имеет максимум (т. Е. Самый последний) из двух столбцов даты ).
Старый поток, который я знаю, но это работает для дат (используется формула выше): dateadd(dd, ((datediff(dd, 0, [Date1]) + datediff(dd, 0, [Date2])) + abs(datediff(dd, 0, [Date1]) - datediff(dd, 0, [Date2]))) / 2, 0)
Поскольку это было не сразу очевидно, это работает, потому что выражение ABS вычисляет величину разницы между минимальным и максимальным значением. Если добавить это обратно к сумме минимального и максимального значений, сумма будет в два раза больше максимального значения (которое всегда делится на 2). Деление на 2 возвращает максимальное значение. Я считаю, что вы можете изменить это, чтобы достичь функциональности MIN, вычитая выражение ABS вместо добавления.
Потеря точности при использовании типов с плавающей запятой означает, что вы можете не получить фактическое максимальное значение, а только число, которое действительно близко.
@futureSPQR: CAST (0.5 * ((CAST (@ val1 as float) + CAST (@ val2 AS float)) + ABS (cast (@ val1 as float) - CAST (@ val2 AS float))) AS datetime)
Проголосовали против, потому что он использует смекалку там, где доступно чистое решение. Он также выдает число, которое не может быть гарантировано равным какому-либо столбцу из-за арифметических ошибок округления. Следует использовать оператор CASE (или эквивалентную функцию IIF, если она доступна). Гринольдман сказал это правильно.
Если любое значение равно нулю, вы получите ноль. Наверное, не то, что нужно.
Кто-то отработал доказательство ♥
Определенно элегантное решение, которое избегает сравнения ... Спасибо!
DECLARE @MAX INT
@MAX = (SELECT MAX(VALUE)
FROM (SELECT 1 AS VALUE UNION
SELECT 2 AS VALUE) AS T1)
Я даю этому решению +1, потому что оно соответствует DRY (не повторяйтесь) без необходимости писать UDF. Также замечательно, если оба значения, которые вам нужно проверить, являются результатами другого sql, например, в моем случае я хочу найти большее из двух операторов select count (*).
Я ненавижу то, что мне приходится прибегать к этому решению, но это, безусловно, лучший способ сделать это в SQL Server, пока они не добавят встроенную поддержку GREATEST или встроенного MAX. Спасибо за публикацию - +1 вам!
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
Для ответа выше относительно больших чисел вы можете выполнить умножение перед сложением / вычитанием. Он немного крупнее, но не требует гипсовой повязки. (Я не могу говорить о скорости, но предполагаю, что все еще довольно быстро)
SELECT 0.5 * ((@val1 + @val2) + ABS(@val1 - @val2))
Изменения к
SELECT @val1*0.5+@val2*0.5 + ABS(@val1*0.5 - @val2*0.5)
по крайней мере, альтернатива, если вы хотите избежать кастинга.
Подзапросы могут обращаться к столбцам из внешнего запроса, поэтому вы можете использовать этот подход для использования агрегатов, таких как 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
Хороший! Он очень хорошо масштабируется.
+1, чтобы показать Любовь к тем, кто еще в 2005 году. Не знаю, как я пропустил этот ответ. Под обложками, я полагаю, он работает так же хорошо, как то, что я опубликовал 2 года спустя. Оглядываясь назад, я должен был это понять и обновить ваш ответ, включив в него более новый синтаксис 2008 года. Извините, я хотел бы поделиться с вами своими баллами сейчас.
@MikeTeeVee - Спасибо! Да под одеялом план будет такой же. Но синтаксис VALUES лучше.
хороший ответ, потому что он работает во всех версиях, включая новый Azure DW / synapse, который не поддерживает VALUES ()
В простейшем виде ...
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
Все кредиты и голоса должны идти на Ответ Свена на связанный вопрос: «SQL MAX из нескольких столбцов?»
Я говорю, что это "лучший ответ", потому что:
+1 единственный ответ, не требующий доступа для создания процедуры / функций!
Именно такой ответ я искал. Использование функций происходит медленно, и это также будет работать с датами, что мне и нужно.
+1 Отлично работает, особенно для сравнения более двух столбцов!
Это менее производительно, чем решение CASE WHEN, которое требует только вычисления скаляра.
@tukushan Я не заметил никаких проблем с производительностью, используя это в своих запросах (и я использовал его несколько раз для заполнения своего хранилища данных, а также в нашей онлайн-отчетности). С помощью оператора CASE вам нужно будет добавить проверки NULL для его правильной работы, и мы все знаем, что проверка на NULL будет снижать производительность, если вы пытаетесь доить каждую наносекунду. Честно говоря, я не нашел времени, чтобы запустить кучу тестов для сравнения, но я не запускал эти тесты, потому что они настолько молниеносные, что мне не нужно искать более быстрый вариант.
Возможно, вы правы - я тоже не особо разбирался в этом. Но я заметил, что план запроса, созданный для вышеуказанного, дороже, чем решение CASE.
Хотя более простой синтаксис может никогда не стоить снижения производительности при определении MAX из 2 значений, это может быть другое дело с большим количеством значений. Даже при получении MAX, равного 4 значениям, предложения CASE становятся длинными, неуклюжими и подверженными ошибкам, если генерируются вручную, в то время как предложение VALUES остается простым и понятным.
Не может использоваться, если результат требуется в агрегатной функции: Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
@Thorarin Просто используйте @variable для сохранения результата, а затем агрегируйте его
Случайно и по незнанию нажал «против» и больше не может его изменить. Извиняюсь! Ответ действительно помог мне!
И синтаксис, совместимый с SQL Server 2005, в моем нелюбимом ответе, опубликованном двумя годами ранее! stackoverflow.com/a/3989370/73226
Предупреждение - я использовал это в операторе UPDATE в форме SET x = (SELECT MAX (CopyCount) FROM (VALUES (x - 1), (0)) AS Copies (CopyCount)), и он работал ужасно и иногда приводил к дал мне ошибки, когда база данных больше не могла обновлять строку.
Это так просто:
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;
См. Комментарий @Neil к предыдущему ответу SELECT dbo.InlineMax (CAST (0.5 AS FLOAT), 100) неверен.
SQL Server 2012 представил IIF:
SELECT
o.OrderId,
IIF( ISNULL( o.NegotiatedPrice, 0 ) > ISNULL( o.SuggestedPrice, 0 ),
o.NegotiatedPrice,
o.SuggestedPrice
)
FROM
Order o
При использовании IIF рекомендуется обрабатывать NULL, потому что NULL на любой стороне вашего boolean_expression заставит IIF вернуть false_value (в отличие от NULL).
Ваше решение не будет правильно обрабатывать NULL, когда другое значение отрицательно, это вернет 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 и новее)
IIF(a>b, a, b)
Вот и все.
(Подсказка: будьте осторожны, если любой из них будет null, поскольку результат a>b будет ложным, если любой из них равен нулю. Таким образом, в этом случае результатом будет b)
Если одно из значений NULL, результатом всегда будет второе.
IIF () - это синтаксический сахар для оператора CASE. Если одно из значений условного оператора CASE равно NULL, результатом будет второе значение (ELSE).
@xxyzzy, потому что утверждение NULL > 1234 неверно
поэтому IIF(a>b, a, COALESCE(b,a)) дает значение, когда существует только один
Вот пример случая, который должен обрабатывать значения NULL и работать со старыми версиями MSSQL. Это основано на встроенной функции в одном из популярных примеров:
case
when a >= b then a
else isnull(b,a)
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
Вот версия IIF с обработкой NULL (на основе ответа 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]
В Presto вы можете использовать
SELECT array_max(ARRAY[o.NegotiatedPrice, o.SuggestedPrice])
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
Для объяснения, пожалуйста, обратитесь к этой статье: red-gate.com/simple-talk/sql/sql-training/…
Пожалуйста, не включайте необходимую информацию в свой код просто по ссылке. Представьте, что однажды эта ссылка истечет, и тогда ваш ответ будет бесполезен. Поэтому, пожалуйста, добавьте основную информацию прямо в свой ответ. Но вы все равно можете предоставить эту ссылку в качестве ресурса, чтобы другие могли найти дополнительную информацию.
-- 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
В SQL Server 2012 или более поздней версии вы можете использовать комбинацию IIF и ISNULL (или COALESCE), чтобы получить максимум 2 значения.
Даже если 1 из них равен NULL.
IIF(col1 >= col2, col1, ISNULL(col2, col1))
Или, если вы хотите, чтобы он возвращал 0, когда оба равны NULL
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
Это дает дополнительное преимущество в том, что он может одновременно вычислять другие вещи.
В 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)
Это реализовано в большинстве других баз данных как функция
GREATEST; SQLite эмулирует поддержку, позволяя использовать несколько столбцов в агрегатеMAX.