日期列表之间的天数

时间:2019-02-15 16:14:25

标签: sql-server

我有一个临时表,其中包含交易,日期和交易量。我需要以动态方式计算生效日期之间的日期。同时,这也使情况变得复杂,每笔交易的第一个都是过去的交易,但是代表当前交易量。因此,对于该行,我需要返回从今天到该交易的下一个生效日期的天数。此外,在每笔交易的最后生效日期,我必须运行一个子查询以从另一个临时表中获取合同结束日期。

临时表的样本和所需的样本返回: Sample

1 个答案:

答案 0 :(得分:0)

这是一个探索的选择。

基本上,每条记录的要求是:

  1. 基于Deal_ID的先前记录的有效日期-LAG()
  2. 今天后的下一个有效日期基于Deal_ID-子查询

然后,您可以根据这些值评估并确定天数。

这是一个临时表和一些示例数据:

CREATE TABLE #Deal
    (
        [Row_ID] INT
      , [Deal_ID] BIGINT
      , [EffectiveDate] DATE
      , [Volume] BIGINT
    );

INSERT INTO #Deal (
                      [Row_ID]
                    , [Deal_ID]
                    , [EffectiveDate]
                    , [Volume]
                  )
VALUES ( 1, 1479209, '2018-11-01', 5203 )
     , ( 2, 1479209, '2019-03-01', 2727 )
     , ( 3, 1479209, '2019-04-01', 1615 )
     , ( 4, 1479209, '2019-06-01', 1325 )
     , ( 5, 1598451, '2018-12-01', 2000 )
     , ( 6, 1598451, '2019-04-01', 4000 )
     , ( 7, 1598451, '2019-08-01', 4000 );

以下是使用LAG()和子查询的示例查询:

       SELECT *
                -- LAG here partitioned by the Deal_ID, will return NULL if first record.
            , LAG([dl].[EffectiveDate], 1, NULL) OVER ( PARTITION BY [dl].[Deal_ID]
                                                        ORDER BY [dl].[EffectiveDate]
                                                      ) AS [PreviousRowEffectiveData]
                --Sub query to get min EffectiveDate that is greater than today
            , (
                  SELECT MIN([dl1].[EffectiveDate])
                  FROM   #Deal [dl1]
                  WHERE  [dl1].[Deal_ID] = [dl].[Deal_ID]
                         AND [dl1].[EffectiveDate] > GETDATE()
              ) AS [NextEffectiveDateAfterToday]
       FROM   #Deal [dl]

为您提供这些结果:

Row_ID      Deal_ID              EffectiveDate Volume               PreviousRowEffectiveData NextEffectiveDateAfterToday
----------- -------------------- ------------- -------------------- ------------------------ ---------------------------
1           1479209              2018-11-01    5203                 NULL                     2019-03-01
2           1479209              2019-03-01    2727                 2018-11-01               2019-03-01
3           1479209              2019-04-01    1615                 2019-03-01               2019-03-01
4           1479209              2019-06-01    1325                 2019-04-01               2019-03-01
5           1598451              2018-12-01    2000                 NULL                     2019-04-01
6           1598451              2019-04-01    4000                 2018-12-01               2019-04-01
7           1598451              2019-08-01    4000                 2019-04-01               2019-04-01

现在,如果我正确理解的话,我们可以在子查询中使用它,然后为DAYS实施业务规则:

  • Deal_ID的第一行,即从今天之后的下一个生效日期到今天的天数。
  • 如果不是第一天,则是从上一个生效日期到行生效日期的天数。

查询示例:

SELECT *
        --Case statement, if previousrow null(first record) difference in days of datday and NextEfectiveDateAfterToday
        --Else we will do the difference in days of previousrow and this rows effective date.
     , CASE WHEN [Deal].[PreviousRowEffectiveData] IS NULL THEN DATEDIFF(DAY, GETDATE(), [Deal].[NextEffectiveDateAfterToday])
            ELSE DATEDIFF(DAY, [Deal].[PreviousRowEffectiveData], [Deal].[EffectiveDate])
       END AS [DAYS]
FROM   (
           SELECT *
                    -- LAG here partioned by the Deal_ID, we'l return NULL if first record.
                , LAG([dl].[EffectiveDate], 1, NULL) OVER ( PARTITION BY [dl].[Deal_ID]
                                                            ORDER BY [dl].[EffectiveDate]
                                                          ) AS [PreviousRowEffectiveData]
                    --Sub query to get min EffectiveDate that is greater than today
                , (
                      SELECT MIN([dl1].[EffectiveDate])
                      FROM   #Deal [dl1]
                      WHERE  [dl1].[Deal_ID] = [dl].[Deal_ID]
                             AND [dl1].[EffectiveDate] > GETDATE()
                  ) AS [NextEffectiveDateAfterToday]
           FROM   #Deal [dl]
       ) AS [Deal];

为我们提供以下最终结果:

Row_ID      Deal_ID              EffectiveDate Volume               PreviousRowEffectiveData NextEffectiveDateAfterToday DAYS
----------- -------------------- ------------- -------------------- ------------------------ --------------------------- -----------
1           1479209              2018-11-01    5203                 NULL                     2019-03-01                  14
2           1479209              2019-03-01    2727                 2018-11-01               2019-03-01                  120
3           1479209              2019-04-01    1615                 2019-03-01               2019-03-01                  31
4           1479209              2019-06-01    1325                 2019-04-01               2019-03-01                  61
5           1598451              2018-12-01    2000                 NULL                     2019-04-01                  45
6           1598451              2019-04-01    4000                 2018-12-01               2019-04-01                  121
7           1598451              2019-08-01    4000                 2019-04-01               2019-04-01                  122