【问题标题】:Return previous record for holiday/weekends返回假期/周末的先前记录
【发布时间】:2016-09-12 01:08:59
【问题描述】:

一张表有股票的名称、价值和股票的生效日期,假期/周末不会有任何条目。如果我通过的日期范围包含节假日/周末,我想返回以前的日期记录。

例如

表名:库存

    ID  Name    Value   EffectiveDate
    1   IBM 200.0000    2015-12-31 00:00:00.000
    2   IBM 201.4500    2016-01-04 00:00:00.000
    3   IBM 201.0000    2016-01-05 00:00:00.000
    4   IBM 202.0000    2016-01-06 00:00:00.000

   SELECT Name, Value, EffectiveDate FROM Stock WHERE Name = 'IBM' AND  EffectiveDate >= '20151231' AND EffectiveDate <= '20160105'

以上查询返回前 3 条记录,但我想返回以下结果:

    Name    Value   EffectiveDate   ActualDate
    IBM 200.0000    2015-12-31      2015-12-31 
    IBM 200.0000    2015-12-31      2016-01-01 
    IBM 200.0000    2015-12-31      2016-01-02 
    IBM 200.0000    2015-12-31      2016-01-03 
    IBM 201.4500    2016-01-04      2015-01-04 
    IBM 201.0000    2016-01-05      2015-01-05 

01/01/2016 至 03/01/2016 是节假日/周末。如果我通过假期/周末日期,我有一个返回前一个日期的函数。任何人都可以帮助在 SQL Server 中编写查询以实现上述目的吗?

【问题讨论】:

    标签: sql-server sql-server-2008


    【解决方案1】:
    DECLARE @table TABLE (
      id int,
      name varchar(20),
      value decimal(10, 4),
      EffectiveDate datetime
    )
    INSERT INTO @table
      VALUES (1, 'IBM', 200.0000, '2015-12-31 00:00:00.000')
      , (2, 'IBM', 201.4500, '2016-01-04 00:00:00.000')
      , (3, 'IBM', 201.0000, '2016-01-05 00:00:00.000')
      , (4, 'IBM', 202.0000, '2016-01-06 00:00:00.000')
    
    DECLARE @MinDate datetime = '20151231',
            @MaxDate datetime = '20160105';
    
    WITH Dates AS (
        SELECT @MinDate AS ActualDate
      UNION ALL
        SELECT DATEADD(day, 1, ActualDate)
        FROM Dates
        WHERE ActualDate < @MaxDate
    )
    SELECT [Table].name 
          ,[Table].value
          ,[Table].EffectiveDate
          ,[Dates].ActualDate
    FROM Dates
         CROSS APPLY (
             SELECT MAX(EffectiveDate) AS LastEffectiveDate
             FROM @table AS [Table]
             WHERE [Table].EffectiveDate <= Dates.ActualDate
         ) AS CA1
         INNER JOIN @table AS [Table]
             ON [Table].EffectiveDate = CA1.LastEffectiveDate
    

    【讨论】:

    • 嗨@adrianm,只是想知道,您能解释一下为什么在这种情况下使用交叉应用吗?
    • 这只是ON [Table].EffectiveDate = (SELECT MAX(EffectiveDate) ...)的“更易于阅读”的版本
    【解决方案2】:

    如果EffectiveDate 是周末,则以下代码将根据上一个日期的要求返回ActualDate,但是要包含银行假期的逻辑,您需要在表中定义这些逻辑,然后将更多逻辑添加到下面。

    SELECT Name, Value, EffectiveDate, 
    CASE WHEN datename(dw,EffectiveDate) = 'Saturday' 
         THEN DATEADD(DAY, -1, EffectiveDate)
         WHEN datename(dw,EffectiveDate) = 'Sunday'
         THEN DATEADD(DAY, -2, EffectiveDate)
    END AS ActualDate
    FROM Stock 
    WHERE Name = 'IBM' 
    AND EffectiveDate BETWEEN '20151231' AND '20160105'
    

    【讨论】:

      【解决方案3】:

      这可能不是一个完美的解决方案,但这可以解决问题。

      DECLARE @table TABLE (
        id int,
        name varchar(20),
        value decimal(10, 4),
        EffectiveDate datetime
      )
      INSERT INTO @table
        VALUES (1, 'IBM', 200.0000, '2015-12-31 00:00:00.000')
        , (2, 'IBM', 201.4500, '2016-01-04 00:00:00.000')
        , (3, 'IBM', 201.0000, '2016-01-05 00:00:00.000')
        , (4, 'IBM', 202.0000, '2016-01-06 00:00:00.000')
      
      DECLARE @MinDate datetime = '20151231',
              @MaxDate datetime = '20160105';
      
      SELECT
        id,
        (CASE
          WHEN Data.Value IS NULL THEN (SELECT TOP (1)
              value
            FROM @table AS T1
            WHERE T1.EffectiveDate < Data.FinalDate
            ORDER BY FinalDate DESC)
          ELSE Data.value
        END),
        FinalDate
      FROM (SELECT
        id,
        name,
        value,
        (CASE
          WHEN EffectiveDate IS NULL THEN Date
          ELSE EffectiveDate
        END) AS FinalDate
      FROM @table T
      FULL OUTER JOIN (SELECT TOP (DATEDIFF(DAY, @MinDate, @MaxDate) + 1)
        Date = DATEADD(DAY, ROW_NUMBER() OVER (ORDER BY a.object_id) - 1, @MinDate)
      FROM sys.all_objects a
      CROSS JOIN sys.all_objects b) H
        ON T.EffectiveDate = H.Date) Data
      ORDER BY finaldate
      

      【讨论】:

      • 感谢 Krishna.. 我希望您同意 Adrian 的回复是一个完美的解决方案。
      • 是的。这就是我 +1 的原因
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-03
      • 1970-01-01
      • 2017-04-14
      • 1970-01-01
      • 1970-01-01
      • 2020-10-18
      相关资源
      最近更新 更多