Есть у меня логика в приложении на c#, которую я был вынужден начать дублировать на slq server в представлениях и хранимках и столкнулся с тем, что расчёт происходит различным образом.
Наглядный пример. Некоторая сущность с полем типа decimal, Code First, табличка на SQL Server, тип тоже decimal.
В C# Math.Round в случае числа с половинкой округляет данные к ближайшему чётному числу (MidpointRounding.ToEven):
decimal val1 = 766.5m;
decimal val2 = 767.5m;
Console.WriteLine(Math.Round(766.5m)); // 766
Console.WriteLine(Math.Round(767.5m)); // 768
При этом ROUND в SQL таких настроек не поддерживает:
DECLARE @val1 decimal = 766.5;
DECLARE @val2 decimal = 767.5;
SELECT ROUND(@val1, 0); -- 767
SELECT ROUND(@val2, 0); -- 768
Каким образом сделать поведение ROUND в MS SQL таким же, как в c#?
PS Версия сервера: MSSQL2016 (13.0.1601.5), .net core 2.1
Если я правильно понял задачу, то можно так:
DECLARE @T TABLE (col decimal(18,2))
INSERT @T (col)
VALUES (-122), (-122.5),
(-123), (-123.5),
(-124), (-124.5),
(122), (122.5),
(123), (123.5),
(124), (124.5)
SELECT col
,IIF(CEILING(col) % 2 = 0, CEILING(col), FLOOR(col))
FROM @T
Функция CEILING - возвращает наименьшее целое число, большее или равное переданному в неё числовому выражению;
Функция FLOOR - возвращает наибольшее целое число, меньшее или равное переданному в неё числовому выражению.
В выражении CEILING(col) % 2 = 0
мы проверяем число с откинутой дробной частью на чётность (остаток от деления на 2 должен быть равен нулю). Если число чётное, то берём наименьшее целое, в противном случае наибольшее целое.
Конструкцию IIF так же можно заменить на CASE для версий SQL меньше 2012, которые не поддерживают IIF:
CASE CEILING(col) % 2 WHEN 0 THEN CEILING(col) ELSE FLOOR(col) END
P.S. Запихивать эту конструкцию в функцию я бы не стал. Вообще в SQL Server от функций лучше держаться подальше без крайней нужды, так как они могут представлять собой подводные камни в плане производительности запросов.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Нужно отслеживать состояние переменнойПытался сделать такой код:
Возникла необходимость создать ограничение для ввода данных в textBox