Как составить прогноз дохода в SQL? - PullRequest
0 голосов
/ 03 декабря 2009

У меня есть таблица со списком позиций строки контракта в виде

CREATE TABLE contracts_lines (
  contract_id integer,
  product_id integer,
  contract_line_start datetime,
  contract_line_end datetime,
  amount float
)

То, что я хотел бы создать, - это ПРОСМОТР (или заполнение таблицы), который позволяет мне определить, какой доход я могу ожидать каждый месяц - у нас есть простое правило, что каждая строка распознается равномерно в течение срока действия строки т.е. daily revenue = amount / (contract_line_end - contract_line_start))

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

montly_revenue_forecast (
  year int,
  month int,
  product_id int,
  contract_id int,
  amount float
)

Я хотел бы сделать прогноз на 12 месяцев, начиная со дня его запуска, и он будет проходить через SSIS, поэтому у меня есть доступ к его конструкциям (таким как циклы и т. Д.). Я бы предпочел не писать никаких хранимые процедуры.

Любая помощь приветствуется

Ответы [ 2 ]

3 голосов
/ 03 декабря 2009

Что вам нужно сделать, это сначала сгенерировать последовательность дат для каждого контракта / продукта, а затем использовать последовательность для группировки.

Наиболее удобный способ генерации последовательности - использовать довольно плохо документированную таблицу spt_values, например:

WITH Contracts_CTE (contract_id, product_id, contract_day, amount) AS
(
    SELECT 
        cl.contract_id,
        cl.product_id,
        DATEADD(DAY, v.number, cl.contract_line_start),
        cl.amount / DATEDIFF(DAY, cl.contract_line_start, cl.contract_line_end)
    FROM contracts_lines cl
    CROSS JOIN master.dbo.spt_values v
    WHERE v.type = 'P'
    AND DATEADD(DAY, v.number, cl.contract_line_start) < cl.contract_line_end
)
SELECT
    DATEPART(YEAR, c.contract_day) AS contract_year,
    DATEPART(MONTH, c.contract_day) AS contract_month,
    c.product_id,
    c.contract_id,
    SUM(Amount) AS contract_amount
FROM Contracts_CTE c
GROUP BY
    c.product_id,
    c.contract_id,
    DATEPART(YEAR, c.contract_day),
    DATEPART(MONTH, c.contract_day)

Просто предостережение - числа в spt_values ​​изменяются только от 0 до 2047, поэтому если у вас есть контракты, срок действия которых превышает 5 лет, вам нужно будет создать более длинную последовательность. Самый простой способ сделать это - CROSS JOIN присоединить таблицу spt_values ​​к себе, т. Е .:

SELECT (v1.number * 2048) + v2.number
FROM master.dbo.spt_values v1
CROSS JOIN master.dbo.spt_values v2
WHERE v1.type = 'P'
AND v2.type = 'P'
AND ((v1.number * 2048) + v2.number) < 100000

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

0 голосов
/ 03 декабря 2009

Это не полное решение, но вы, вероятно, хотите рассчитать ежемесячный доход для каждого проекта на основе, скажем, 30-дневного месяца.

Примерно так:

select contract_id, product_id, 
       amount / (datediff(day, contract_line_start, contract_line_end)) * 30 as MontlyRevenue
from contracts_lines
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...