Хранение операторов с операндами в таблице в SQL Server - PullRequest
0 голосов
/ 18 октября 2018

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

Например, мы продаем договор на обслуживание автомобиля, гдеДля определенного автомобиля резервная цена контракта составляет 36 долларов США.Дилер увеличивает каждый резерв на 30% (до 47 долл. США), добавляет к резервной цене премию в размере 33 долл. США (в настоящее время 80 долл. США) и добавляет набор комиссионных, таких как комиссионные и административные расходы, для доведения общей суммы контракта до 235 долл. США..

Резервная цена одинакова для каждого дилера в этой программе, но все они используют разные увеличения, которые либо равны, либо в процентах.Конечно, для каждого контракта существуют десятки параметров.

Мой вопрос такой: : могу ли я сохранить таблицу параметров, таких как "x * 1.3" или "y + 33", которые проиндексированык уникальному идентификатору, а затем соединить или перекрестно применить эту таблицу к одному полному значению, такому как указанная выше резервная цена?

Я посмотрел на SQL Server «табличные параметры», но я не вижу изпримеры MSDN, если они применимы к моему делу.

Большое спасибо за ваши добрые ответы.

РЕДАКТИРОВАТЬ: Как я и опасался, мой пример, кажется, слишкомэзотерика (моя вина).Так что учтите это: Twinings рекомендует разные температуры для приготовления разных видов чая.В зависимости от вашей высоты, ваша точка кипения может отличаться.Таким образом, должен быть способ хранения таблицы значений, которая выглядит следующим образом -
image

Пользователь вводит почтовый индекс с соответствующей отметкой, а SQL Server вычисляет и возвращает правильное значениезаваривать температуру для вас.Это лучше пример?

Опять же, спасибо тем, кто уже внес свой вклад.

Ответы [ 2 ]

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

Вы можете использовать очень простую структуру для хранения затрат:

DECLARE @costs TABLE (
    ID INT,
    Perc DECIMAL(18, 6),
    Flat DECIMAL(18, 6)
);

Столбец Perc представляет процент от базовой цены.В этой структуре можно хранить сложные вычисления , но она становится некрасивой .Например, если у нас есть:

  1. Базовая цена: 100
  2. Фиксированная плата: 20
  3. Налог: 11,5%
  4. Плата за обработку: 3%

Тогда он будет храниться как:

INSERT INTO @costs VALUES
-- op example
(1, 0.0,  NULL),
(1, 0.3,  NULL),
(1, NULL, 33.0),
(1, NULL, 155.0),
-- above example
(2, 0.0,          NULL),
(2, NULL,         20.0),
(2, 0.115,        NULL),
(2, NULL,         20.0 * 0.115),
(2, 0.03,         NULL),
(2, NULL,         20.0 * 0.03),
(2, 0.115 * 0.03, NULL),
(2, NULL,         20 * 0.115 * 0.03);

И будет запрашиваться как:

DECLARE @tests TABLE (
    ID INT,
    BasePrice DECIMAL(18, 2)
);
INSERT INTO @tests VALUES
(1, 36.0),
(2, 100.0);

SELECT t.ID, SUM(
    BasePrice * COALESCE(Perc, 0) + 
    COALESCE(Flat, 0)
) AS TotalPrice
FROM @tests t
INNER JOIN @costs c ON t.ID = c.ID
GROUP BY t.ID
ID | TotalPrice
---+-------------
1  | 234.80000000
2  | 137.81400000

Другое, лучшее решение - использоватьструктура выглядит следующим образом:

DECLARE @costs TABLE (
    ID INT,
    CalcOrder INT,
    PercOfBase DECIMAL(18, 6),
    PercOfPrev DECIMAL(18, 6),
    FlatAmount DECIMAL(18, 6)
);

Где CalcOrder представляет порядок, в котором выполняется расчет (например, налог до сбора за обработку).PercOfBase и PercOfPrev указывают, умножается ли базовая цена или текущая сумма.Это позволяет вам обрабатывать ситуации, когда, например, комиссия добавляется к базовой цене, но она не должна включаться в налог и наоборот.Этот подход требует рекурсивного или итеративного запроса.

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

Я не знаю, нравится ли мне это решение, но, похоже, оно, по крайней мере, работает.Единственный реальный способ итеративного построения итогов - это использовать некоторую форму "цикла", и в наши дни наиболее подходящим способом для этого является использование рекурсивного CTE:

declare @actions table (ID int identity(1,1) not null, ApplicationOrder int not null, 
                        Multiply decimal(12,4), AddValue decimal(12,4))
insert into @actions (ApplicationOrder,Multiply,AddValue) values
(1,1.3,null),
(2,null,33),
(3,null,155)

declare @todo table (ID int not null, Reserve decimal(12,4))
insert into @todo(ID,Reserve) values (1,36)

;With Applied as (
    select
        t.ID, Reserve  as Computed, 0 as ApplicationOrder
    from
        @todo t
    union all
    select a.ID,
      CONVERT(decimal(12,4),
        ((a.Computed * COALESCE(Multiply,1)) + COALESCE(AddValue,0))),
      act.ApplicationOrder
    from
        Applied a
            inner join
        @actions act
            on
                a.ApplicationOrder  = act.ApplicationOrder - 1
), IdentifyFinal as (
    select
        *,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ApplicationOrder desc) as rn
    from Applied
)
select
    *
from
    IdentifyFinal
where
    rn = 1

Здесь я получилпростой набор действий, применяемых к каждой цене (в @actions), и набор цен, к которым они применяются (в @todo).Затем я использую рекурсивный CTE, чтобы применить каждое действие по очереди.

Мой результат:

ID          Computed                                ApplicationOrder rn
----------- --------------------------------------- ---------------- --------------------
1           234.8000                                3                1

Что не далеко от ваших 235 долларов: -)

Я ценючто у вас могут быть разные действия, применимые к каждой конкретной цене, и поэтому вместо вас мой @actions может быть чем-то, что определяет, какие правила применять в каждом конкретном случае.Это может быть один из нескольких CTE до меня, которые выполняют эту работу, возможно, используя другое выражение ROW_NUMBER() для определения правильных значений ApplicationOrder.Вам также может понадобиться больше столбцов и условий соединения в CTE, чтобы удовлетворить это.

Обратите внимание, что я смоделировал действия, чтобы каждый мог применять умножение и / или сложение на каждом этапе.Возможно, вы захотите поиграть с такой идеей (или, например, добавить какой-нибудь флаг «округления», чтобы мы могли в итоге получить значение $ 235).

Applied в конечном итоге содержитначальные значения и каждое промежуточное значение.IdentifyFinal CTE дает нам только окончательные результаты, но вы можете выбрать из Applied вместо того, чтобы просто посмотреть, как это работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...