查看以填充日期空白,但仅限于没有给定日期的记录

时间:2017-04-11 11:32:11

标签: sql-server sql-server-2012

我有一个基本的2列数据表,其中包含名称(VARCHAR)和日期(DATE),即每日扫描过程的结果。这些名称通常会在多个日期重复出现,但它们可能每天都有所不同。没有名称/日期组合可以重复(复合主键)。我正在使用SQL Server 2012。

MyName | MyDate
------ | ----------
ABC    | 2017-04-11
DEF    | 2017-04-11
GHJ    | 2017-04-11
ABC    | 2017-04-10
DEF    | 2017-04-10
GHJ    | 2017-04-10
ABC    | 2017-04-08
GHJ    | 2017-04-08

我需要创建一个视图,在两个定义的日期之间从表中提取此信息,如果该范围内的任何给定日期有 记录,根据可用的上一个日期生成该日期的记录。

因此,使用上面的示例,对于2017-04-08到2017-04-11的日期范围,没有2017-04-09的记录 - 所以我想复制2017-04-08的记录(记录可用的上一个日期)并将它们包含在返回的数据集中,ála:

  MyName | MyDate
-------- | ----------
  ABC    | 2017-04-11
  DEF    | 2017-04-11
  GHJ    | 2017-04-11
  ABC    | 2017-04-10
  DEF    | 2017-04-10
  GHJ    | 2017-04-10
**ABC    | 2017-04-09**
**GHJ    | 2017-04-09**
  ABC    | 2017-04-08
  GHJ    | 2017-04-08

我希望将此作为一个视图,而不是将“间隙填充”过程作为扫描/导入到表格的一部分,以便我可以轻松地回顾性地识别扫描可能具有的日期失败(但仍然能够生成一个包含每个日期的完整数据集,即使差距只是捏造)

我已经在网站上搜寻寻找解决方案,但我发现的唯一一个似乎只能容纳每个日期只有一条记录的表格,并相应填补“单一”差距(通常为零而不是采用以前的值)

我可以生成定义范围内所有日期的临时表,并使用外部联接从表中添加真实数据,但是如果每个日期可以有多个记录,我如何填补空白?而且我只考虑在给定日期没有记录的情况下存在差距?

1 个答案:

答案 0 :(得分:0)

您可以使用表值函数,它允许您使用参数,因此无需对其进行硬编码。

返回的表包含一个额外的列Ins;原始数据为0,插入为1。

Rextester demo

如果您更喜欢视图,则可以轻松提取逻辑。

create function myFun(@start date, @end date) 
returns @result table (MyName varchar(10), MyDate date, Ins bit) as
begin
;
    with dates as (
        SELECT  DATEADD(DAY, nbr - 1, @start) dt
        FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY c.object_id ) AS Nbr
                  FROM      sys.columns c
                ) nbrs
        WHERE   nbr - 1 <= DATEDIFF(DAY, @start, @end)
    ), last_avail as (
        select dates.dt, max(t.MyDate) prev_dt
        from dates join t on dates.dt >= t.MyDate
        group by dates.dt
    ), empty as (
        select * from last_avail where dt <> prev_dt
    )
    insert @result (MyName, MyDate, Ins)
    select MyName, MyDate, 0 from t
    union all
    select t.MyName, x.dt, 1
    from empty x join t on x.prev_dt = t.MyDate;

    return;
end

用法示例:

declare @start date, @end date;

set @start = '2017-04-08';
set @end = '2017-04-11';
select * from dbo.myFun(@start, @end) order by MyDate desc, MyName asc;

<强>归因

已发现扮演日历表角色的公用表表达式here