SQL-在日期之间分配金额

SQL-在日期之间分配金额,sql,sql-server,database,forecasting,Sql,Sql Server,Database,Forecasting,我想预测两个日期之间的金额。金额在各日期之间均匀分布-参考下表。(希望)应该是简单的-有什么想法吗 源表如下所示: +-----------+---------------+---------------+------+--------------+----------------+ | Project | Start Date | End Date | Days | Total Budget | Budget Per Day | +-----------+---------

我想预测两个日期之间的金额。金额在各日期之间均匀分布-参考下表。(希望)应该是简单的-有什么想法吗

源表如下所示:

+-----------+---------------+---------------+------+--------------+----------------+
|  Project  |  Start Date   |   End Date    | Days | Total Budget | Budget Per Day |
+-----------+---------------+---------------+------+--------------+----------------+
| Project 1 | Jan. 01, 2017 | Apr. 11, 2017 |  100 |          100 |  1.00          |
| Project 2 | Feb. 05, 2017 | Apr. 06, 2017 |   60 |          200 |  3.33          |
| Project 3 | Feb. 03, 2017 | May. 03, 2017 |   89 |           50 |  0.56          |
| Project 4 | Jan. 01, 2017 | Aug. 04, 2017 |  215 |          300 |  1.40          |
+-----------+---------------+---------------+------+--------------+----------------+
+-----------+---------------+--------+
|  Project  |      Day      | Budget |
+-----------+---------------+--------+
| Project 1 | Jan. 01, 2017 |  1.00  |
| Project 1 | Jan. 02, 2017 |  1.00  |
| Project 1 | Jan. 03, 2017 |  1.00  |
| Project 1 | Jan. 04, 2017 |  1.00  |
| Project 1 | Jan. 05, 2017 |  1.00  |
| …         | …             | …      |
+-----------+---------------+--------+
生成的表应如下所示:

+-----------+---------------+---------------+------+--------------+----------------+
|  Project  |  Start Date   |   End Date    | Days | Total Budget | Budget Per Day |
+-----------+---------------+---------------+------+--------------+----------------+
| Project 1 | Jan. 01, 2017 | Apr. 11, 2017 |  100 |          100 |  1.00          |
| Project 2 | Feb. 05, 2017 | Apr. 06, 2017 |   60 |          200 |  3.33          |
| Project 3 | Feb. 03, 2017 | May. 03, 2017 |   89 |           50 |  0.56          |
| Project 4 | Jan. 01, 2017 | Aug. 04, 2017 |  215 |          300 |  1.40          |
+-----------+---------------+---------------+------+--------------+----------------+
+-----------+---------------+--------+
|  Project  |      Day      | Budget |
+-----------+---------------+--------+
| Project 1 | Jan. 01, 2017 |  1.00  |
| Project 1 | Jan. 02, 2017 |  1.00  |
| Project 1 | Jan. 03, 2017 |  1.00  |
| Project 1 | Jan. 04, 2017 |  1.00  |
| Project 1 | Jan. 05, 2017 |  1.00  |
| …         | …             | …      |
+-----------+---------------+--------+

旁注:这样做的目的是方便地进行不同的汇总:按月、按年等,并最终进行不同的分配,例如前10%的天数内预算的10%,等等。对于如何最好地做到这一点,任何建议都将不胜感激。

首先,为自己生成一个日历表。它们非常有用

CREATE TABLE dbo.tCalendar(
    Date_Value DATE PRIMARY KEY NOT NULL,
    Year AS (DATEPART(YEAR, Date_Value)) PERSISTED,
    Month AS (DATEPART(MONTH, Date_Value)) PERSISTED,
    Day AS (DATEPART(DAY, Date_Value)) PERSISTED,
    Day_Of_Year AS (DATEPART(DY, Date_Value)) PERSISTED,
)

INSERT INTO dbo.tCalendar
SELECT *
FROM (
    SELECT DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY (SELECT 1)) - 1, '2000-01-01') AS d
    FROM        (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1))v(n)
    CROSS JOIN (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1))w(n)
    CROSS JOIN (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1))x(n)
    CROSS JOIN (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1))y(n)
) cal
WHERE cal.d <= '2027-12-31'

--SELECT * FROM  dbo.tCalendar
对于更复杂的分发,一种解决方案是使用一个表来存储按日期范围分配的预算,例如:

CREATE TABLE #Project_Budget_Range(
    Project VARCHAR(100) NOT NULL,
    Range_Start_Date DATE NOT NULL,
    Range_End_Date DATE NOT NULL,
    Range_Days AS (DATEDIFF(DAY, Range_Start_Date, Range_End_Date) + 1) PERSISTED,
    Budget_Allocation_Value DECIMAL(19,0) NULL,
    Budget_Allocation_Pct DECIMAL(9,4) NULL,
    PRIMARY KEY (Project, Range_Start_Date),
    -- End Date >= Start Date
    CONSTRAINT CK_Range_Start_End_Date CHECK (Range_End_Date>=Range_Start_Date),
    -- Either Budget_Allocation_Value or Budget_Allocation_Pct must have a value (but not both)
    CONSTRAINT CK_Allocation_Type CHECK (Budget_Allocation_Value + Budget_Allocation_Pct IS NULL AND COALESCE(Budget_Allocation_Value,Budget_Allocation_Pct) IS NOT NULL)
)

INSERT INTO #Project_Budget_Range
VALUES
('Project 1', '2017-01-01', '2017-01-31', NULL, 0.5),
('Project 1', '2017-02-01', '2017-02-28', 30, NULL),
('Project 1', '2017-03-01', '2017-04-10', 20, NULL)

SELECT * FROM #Project_Budget_Range

SELECT   p.Project
        ,p.Total_Budget
        ,cal.Date_Value
        ,CAST(COALESCE( 
            (b.Budget_Allocation_Pct * p.Total_Budget) / b.Range_Days, -- Allocation by Pct
            b.Budget_Allocation_Value / b.Range_Days -- Allocation by value
        ) AS DECIMAL(19,8)) AS Budget_Allocation
FROM #Project p
    INNER JOIN #Project_Budget_Range b
        ON p.Project = b.Project
    INNER JOIN dbo.tCalendar cal
        ON cal.Date_Value BETWEEN b.Range_Start_Date AND Range_End_Date
WHERE p.Project = 'Project 1'
;

Serge,如果所有项目使用相同的标准-前10%的天数使用预算的10%,后50%的天数使用70%,其余40%的天数使用预算的20%-您将如何调整上述代码?