Объединение возвращает неправильное значение после вызова функции с последующим умножением - PullRequest
0 голосов
/ 03 октября 2018

У меня есть отчет, который представляет информацию, и я получаю противоречивую информацию, основанную на том, что, по-видимому, является проблемой с представлением SQL или, возможно, с функцией SQL, вложенной в представление.Я попытался найти способ отладки SQL View, однако, похоже, что SSMS будет отлаживать только хранимые процедуры, поэтому я не совсем уверен, как пройти и посмотреть, что происходит.Это действительно поставило меня в тупик, и я не могу не задаться вопросом, не является ли это проблемой округления.GetItemAverageCost RETURNS DECIMAL(12,2) и DataType в sitli.QuantityIssuedAtStockUOM - это System.Int64 / bigint (sidenote: я не совсем понимаю, почему LINQPad отображает 2 типа данных для этого столбца. В дереве слева после расширения таблицы sitli и зависания над нимNumberIssuedAtStockUOM всплывет всплывающее окно BigInt NOT NULL, но когда я возьму (100) и наведу курсор мыши на столбец в наборе результатов, появится сообщение System.Int64).Anyroad, вот функция COALESCE.

COALESCE((dbo.GetItemAverageCost(ItemModel.IDItemModel)*sitli.QuantityIssuedAtStockUOM) / ISNULL(NULLIF(ItemModel.UOMFactor, 0),1),0) -- 259.73 --ROUND(COALESCE((dbo.GetItemAverageCost(ItemModel.IDItemModel)*sitli.QuantityIssuedAtStockUOM) / ISNULL(NULLIF(ItemModel.UOMFactor, 0),1),0),2) -- 259.73 --COALESCE(ROUND((dbo.GetItemAverageCost(ItemModel.IDItemModel)*sitli.QuantityIssuedAtStockUOM) / ISNULL(NULLIF(ItemModel.UOMFactor,2), 0),1),0) -- 259.70 --COALESCE((ROUND(dbo.GetItemAverageCost(ItemModel.IDItemModel),2)*sitli.QuantityIssuedAtStockUOM) / ISNULL(NULLIF(ItemModel.UOMFactor, 0),1),0) -- 259.73

оригинал / неверное объединение:

COALESCE(dbo.GetItemAverageCost(ItemModel.IDItemModel)*sitli.QuantityIssuedAtStockUOM,0)

Я не уверен, что еще можно включить, но я не нашел много ресурсов в Интернете, которые бы дали представление о такой ситуации.Заранее большое спасибо за ваше время.

РЕДАКТИРОВАТЬ: GetItemAverageCost:

    ALTER FUNCTION GetItemAverageCost
        (
            @IDItemModel varchar(8000)
        )

        RETURNS DECIMAL(16,4)
        --RETURNS DECIMAL(12,2)
        AS
        BEGIN
        RETURN
        (
        SELECT 
            COALESCE(AVG(poli.UnitPrice),0) as AvgCost
--          COALESCE(ROUND(AVG(poli.UnitPrice),0),2) as AvgCost 260.00
        FROM ItemModel im
        LEFT JOIN VendorItem vi
            ON im.IDItemModel = vi.IDItemModel
        JOIN POLineItem poli
            ON vi.IDVendorItem = poli.IDVendorItem

        WHERE
            im.IDItemModel = @IDItemModel

        GROUP BY
            im.IDItemModel,
            im.ItemNumber
        )
        END

Ответы [ 2 ]

0 голосов
/ 08 октября 2018

Хорошо, большое спасибо всем, кто помогал на этом пути.Было несколько проблем, мешающих мне получить правильный ответ.Во-первых, я работал с неправильным выражением большую часть времени.Во-вторых, после того, как я выяснил, какое выражение использовать, нужно было поместить функцию ROUND в правильное место.

Итак, выражение, которое я должен был использовать для получения моей средней стоимости:

COALESCE(dbo.GetItemAverageCost(Item.IDItemModel) / ISNULL(NULLIF(UOMFactor, 0),1),0)

Когда я переместил это в представление WorkOrderItemInstructionPartCosts, тогда мой отчет принес 10,82 доллара.Затем я добавил *sitli.QuantityIssuedAtStockUOM в строку и получил $ 259,73.Затем я применил функцию ROUND к функции COALESCE и вуаля!получается правильное значение ($ 259,68).

Последняя строка выглядит следующим образом:

ROUND(COALESCE(dbo.GetItemAverageCost(ItemModel.IDItemModel) / ISNULL(NULLIF(UOMFactor, 0),1),0),2)*sitli.QuantityIssuedAtStockUOM

Еще раз спасибо всем, кто помог мне в решении этой проблемы, и извинитеза отсутствие точной информации для начала.Бест, Джонатан

0 голосов
/ 05 октября 2018

чтобы исправить;пусть ваша функция вернет 16,4 вместо 12,2, а затем умножит на два двух десятичных знака после умножения на количество.

"При выполнении данного отчета ошибки не выдаются. Но вычисления выключены.Например, деталь № 12 показывает, что количество 24 было выпущено по цене 259,73 долл. Однако каждая деталь стоит 10,82 долл., Поэтому расчет должен составлять 259,68 долл. Я не уверен, откуда берется разница в 5 центов.результат функции COALESCE выше. Надеемся, что это имеет смысл "

Запустите SQL только для части 12, независимо от функции, и вы увидите, что среднее значение равно 10,822083333333333333333333333333 (10,82 5 / 24ths)

  • 24 * цена за единицу = 259,73
  • цена за единицу = 259,73 / 24
  • цена за единицу = 10,82 5 / 24.

Вы увидите отклонение$ .05

  • 10,82 5/24-е.* 24 = 259,73
  • 10,82 * 24 = 259,68

Эта разница в 5 центов не идет равномерно в оставшиеся 24. Таким образом, ошибка округления при использовании вашей функции.

Когда вы думаете о том, чтобы сходить в магазин и купить что-то, это всегда в размере целой копейки.Когда вы идете на заправку, они взимают до ближайшего 0,00001 цента.(или в вашем случае 4 знака после запятой)

Округление при использовании доли копейки не выполняется до тех пор, пока не умножится на количество или когда фактические денежные средства должны измениться.Если сделать это слишком рано, вы получите ошибки округления, которые вы видите.

Таким образом, вы устраняете ошибки округления, связанные с чрезмерным / недостаточным начислением, и, самое большее, вы будете взимать на долю копейки меньше или больше, чем следовало бы.

...