Страницы

Поиск по вопросам

понедельник, 16 декабря 2019 г.

MS SQL Округление к ближайшему чётному

#c_sharp #sql_server #aspnet_core #entity_framework_core


Есть у меня логика в приложении на 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 
    


Ответы

Ответ 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 от функций лучше держаться подальше без крайней нужды, так как они могут представлять собой подводные камни в плане производительности запросов.

Комментариев нет:

Отправить комментарий