【问题标题】:SQL Server Query - Create New Events to Fill GapsSQL Server 查询 - 创建新事件以填补空白
【发布时间】:2017-09-13 20:19:41
【问题描述】:

我有一个包含列的事件数据表:

  • 资产:资产名称
  • StartDate:活动开始日期
  • EndDate:活动结束日期
  • 代码:事件代码
  • 原因:事件的原因

请看下面的例子

我需要使用特定于单个资产的新事件(具有给定代码和原因值)来填补事件之间的空白。事件需要失效到给定的结束日期。结束日期为 2017-01-02 20:00 的结果见下文

我的 SQL 技能还不错,但这超出了我的能力。任何帮助将不胜感激

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    这应该可以解决问题:

      DECLARE @t TABLE(
        Asset nvarchar(100),
        StartDate datetime,
        EndDate datetime,
        Code nvarchar(100),
        Reason nvarchar(100)
      );
    
      DECLARE @StartDate DATETIME = '2017-01-01 00:00:00';
      DECLARE @EndDate DATETIME = '2017-01-02 20:00:00';
    
      INSERT INTO @t VALUES  ('Asset 1', '2017-01-01 06:00:00', '2017-01-01 09:00:00', 'Code 1', 'Reason 1')
                            ,('Asset 1', '2017-01-01 15:00:00', '2017-01-01 16:00:00', 'Code 1', 'Reason 2')
                            ,('Asset 1', '2017-01-02 12:00:00', '2017-01-02 13:00:00', 'Code 2', 'Reason 2')
                            ,('Asset 2', '2017-01-01 07:00:00', '2017-01-01 08:00:00', 'Code 1', 'Reason 1')
                            ,('Asset 2', '2017-01-01 11:00:00', '2017-01-01 14:00:00', 'Code 1', 'Reason 2')
                            ,('Asset 2', '2017-01-02 15:00:00', '2017-01-02 18:00:00', 'Code 2', 'Reason 2')
                            ,('Asset 2', '2017-01-02 18:00:00', '2017-01-02 19:00:00', 'Code 2', 'Reason 2');
    
      WITH cte AS(
        SELECT *
              ,EndDate AS StartDateNew
              ,ISNULL(LEAD(StartDate) OVER (PARTITION BY Asset ORDER BY StartDate), @EndDate) AS EndDateNew
              ,CASE WHEN EndDate = LEAD(StartDate) OVER (PARTITION BY Asset ORDER BY StartDate) OR EndDate = @EndDate THEN 0 ELSE 1 END AS HasGap
              ,ROW_NUMBER() OVER (PARTITION BY Asset ORDER BY StartDate) AS rn
          FROM @t t
        WHERE StartDate >= @StartDate
      )
      SELECT Asset, StartDate, EndDate, Code, Reason
        FROM cte
      UNION ALL
      SELECT Asset, StartDateNew, EndDateNew, 'Code10', 'Reason10'
        FROM cte
        WHERE HasGap = 1
      UNION ALL
      SELECT Asset, @StartDate AS StartDate, StartDate AS EndDate, 'Code10', 'Reason10'
        FROM cte
        WHERE rn = 1
          AND StartDate > @StartDate
      ORDER BY 1, 2  
    

    【讨论】:

    • 太棒了,谢谢你,你真的帮助了我。如果你也想要一个@StartDate,你会如何修改它?
    • UNION ALLUNION 更受欢迎。 UNION 会产生删除重复项的开销。
    • 我只是稍微编辑了代码以添加 StartDate - 请检查这是否符合您的要求。 :-)
    • 如果你不能使用 LEAD 考虑使用自加入
    • 刚刚修复了我在代码中发现的一个故障:我完全忘记了资产的分区......但是,现在应该是正确的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-19
    • 2020-12-23
    • 1970-01-01
    相关资源
    最近更新 更多