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