我有一个基本的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
我希望将此作为一个视图,而不是将“间隙填充”过程作为扫描/导入到表格的一部分,以便我可以轻松地回顾性地识别扫描可能具有的日期失败(但仍然能够生成一个包含每个日期的完整数据集,即使差距只是捏造)
我已经在网站上搜寻寻找解决方案,但我发现的唯一一个似乎只能容纳每个日期只有一条记录的表格,并相应填补“单一”差距(通常为零而不是采用以前的值)
我可以生成定义范围内所有日期的临时表,并使用外部联接从表中添加真实数据,但是如果每个日期可以有多个记录,我如何填补空白?而且我只考虑在给定日期没有记录的情况下存在差距?
答案 0 :(得分:0)
您可以使用表值函数,它允许您使用参数,因此无需对其进行硬编码。
返回的表包含一个额外的列Ins
;原始数据为0,插入为1。
如果您更喜欢视图,则可以轻松提取逻辑。
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。