如何根据间隔日期和 SQL 服务器上的每日成本 table 计算项目阶段成本

How to calculate Project Phase cost based on interval date and daily cost table on SQL Server

我在 SQL 服务器上有两个 table。第一个 table 存储项目阶段数据:ProjectPhase、StartDate 和 FinishDate。第二个 table 存储 Daily Cost 数据:StartDate、EndDate 和 Daily Cost。两者 table 都具有使用外键列的关系。

我想根据阶段的开始和结束日期以及按比例分配的每日成本计算项目阶段成本。我有一个示例代码如下:

DECLARE @Table1 TABLE
(   
    [ForeignKeyID] INT
    ,[ProjectPhase] CHAR (100)
    ,[StartDate] DATETIME
    ,[FinishDate] DATETIME
);

DECLARE @Table2 TABLE
(   
    [ForeignKeyID] INT
    ,[StartDate] DATETIME
    ,[EndDate] DATETIME
    ,[DailyCost] INT
);

INSERT INTO @Table1 ([ForeignKeyID], [ProjectPhase], [StartDate], [FinishDate])
VALUES  (1, 'Phase 1', '20210101 00:00:00', '20210103 00:00:00')
        ,(1, 'Phase 2', '20210103 00:00:00', '20210105 06:00:00')
        ,(1, 'Phase 3', '20210105 06:00:00', NULL);

INSERT INTO @Table2 ([ForeignKeyID], [StartDate], [EndDate], [DailyCost])
VALUES (1, '20210101 00:00:00', '20210102 00:00:00', 1000)
      ,(1, '20210102 00:00:00', '20210103 00:00:00', 1000)
      ,(1, '20210103 00:00:00', '20210104 00:00:00', 1000)
      ,(1, '20210104 00:00:00', '20210105 00:00:00', 1000)
      ,(1, '20210105 00:00:00', '20210106 00:00:00', 1000);

SELECT 
    xxx
FROM 
    @Table1 t1
    LEFT JOIN @Table2 t2 ON t1.ForeignKeyID = t2.ForeignKeyID

我期待如下结果:

外键ID 项目阶段 开始日期 完成日期 项目阶段成本
1 阶段 1 01/01/2021 00.00 03/01/2021 00.00 2000
1 第 2 阶段 03/01/2021 00.00 05/01/2021 06.00 2250
1 阶段 3 05/01/2021 06.00 750

非常感谢您的帮助或想法。

首先,您需要匹配行。这是一个标准的区间匹配条件:start1 < end2 and end1 > start2。您需要注意有关包含或排除日期的逻辑。

接下来,您需要计算多少天。我们需要在 seconds 内执行此操作,否则我们只能得到一整天的时间。我们取两个表中较晚开始和较早结束的。

然后乘以成本求和。

SELECT 
    t1.ForeignKeyID,
    t1.ProjectPhase,
    t1.StartDate,
    t1.FinishDate,
    ProjectPhaseCost = SUM(
        t2.DailyCost *
        DATEDIFF(second,
            IIF(t1.StartDate > t2.StartDate, t1.StartDate, t2.StartDate),
            IIF(t1.FinishDate < t2.EndDate,   t1.FinishDate, t2.EndDate)
        ) / 86400.0)
FROM @Table1 t1
JOIN @Table2 t2
  ON t1.ForeignKeyID = t2.ForeignKeyID AND
     t1.StartDate < t2.EndDate AND t1.FinishDate > t2.StartDate
GROUP BY
    t1.ForeignKeyID,
    t1.ProjectPhase,
    t1.StartDate,
    t1.FinishDate;