2014-01-13 44 views
4

家伙,我有这个表填补缺失值

+--------------------+------+ 
|stime (datetime) |svalue| 
+--------------------+------+ 
|1/13/2014 8:40:00 AM|5  | 
+--------------------+------+ 
|1/13/2014 8:45:00 AM|6  | 
+--------------------+------+ 
|1/13/2014 8:46:00 AM|5  | 
+--------------------+------+ 
|1/13/2014 8:50:00 AM|4  | 
+--------------------+------+ 

难道在MSSQL可以创建一个查询了所有的资料有1分钟的间隔,如果日期不存在,它取第一下的数据(WHERE stime <=)的值和值分配给时间

所以结果我试图让应该是这样的:

+--------------------+------+ 
|stime (datetime) |svalue| 
+--------------------+------+ 
|1/13/2014 8:40:00 AM|5  | 
+--------------------+------+ 
|1/13/2014 8:41:00 AM|5  | 
+--------------------+------+ 
|1/13/2014 8:42:00 AM|5  | 
+--------------------+------+ 
|1/13/2014 8:43:00 AM|5  | 
+--------------------+------+ 
|1/13/2014 8:44:00 AM|5  | 
+--------------------+------+ 
|1/13/2014 8:45:00 AM|6  | 
+--------------------+------+ 
|1/13/2014 8:46:00 AM|5  | 
+--------------------+------+ 
|1/13/2014 8:47:00 AM|5  | 
+--------------------+------+ 
|1/13/2014 8:48:00 AM|5  | 
+--------------------+------+ 
|1/13/2014 8:49:00 AM|5  | 
+--------------------+------+ 
|1/13/2014 8:50:00 AM|4  | 
+--------------------+------+ 

提前感谢!

+0

在这之前你有没有尝试过任何东西? –

+1

对于“第二”,我们是否应该阅读“分钟”?此外,这是为特定查询更改*结果集*,还是试图永久更改其表中的数据? –

+0

是的,我的意思是分钟抱歉 – user3182508

回答

6

可以使用CTE产生从MIN(stime)MAX(stime)时间序列:

WITH TMinMax as 
(
    SELECT MIN(stime) as MinTime, 
      MAX(stime) as MaxTime 
    FROM T 
) 
,CTE(stime) as 
(
    SELECT MinTime FROM TMinMax 
    UNION ALL 
    SELECT DATEADD(minute,1, stime) 
    FROM CTE 
    WHERE DATEADD(minute,1, stime)<= 
      (SELECT MaxTime from TMinMax) 

) 
select stime, 
     (SELECT TOP 1 svalue 
      FROM T 
      WHERE stime<=CTE.Stime 
     ORDER BY stime DESC) as svalue 
from CTE 
ORDER BY stime 

SQLFiddle demo

+0

非常感谢! – user3182508

0
> DECLARE @stime INT 
SET @stime= (select min(stime) from table group by stime) 
WHILE (@stime <=(select max(stime) from table group by stime)) 
BEGIN 
IF (@stime IN (select stime from table)) 
    begin 
     select stime,svalue from table where stime = @stime 
    end 
ELSE 
    begin 
     select @stime,svalue from table where stime = (select min(stime) from table group by stime) 
    end 

SET @stime = @stime + 1 
END 
GO 
0

试试这个

use tempdb 
go 
/* you need to create this table once and fill it with all necesaary dates */ 
create table dbo.tblSeconds (s datetime) 

declare @s datetime='20140101' 

WHILE @s<'20140102' 
    begin 
     insert into dbo.tblSeconds (s) values (@s) 

     set @s=DATEADD(SECOND,1,@s) 
    end 


create table dbo.YourTable (s datetime, strValue int) 

insert into dbo.YourTable (s,strValue) values('20140101',0),('20140101 05:00',3),('20140101 07:01',5) 


select s.s, (select top(1) t.strValue from dbo.YourTable t where t.s<=s.s order by t.s desc) strValue 
from dbo.tblSeconds s 
order by s.s 

drop table dbo.tblSeconds 
drop table dbo.YourTable 
1

这似乎做的工作:

declare @t table (stime datetime,svalue int) 
insert into @t(stime,svalue) values 
('2014-01-13T08:40:00',5), 
('2014-01-13T08:45:00',6), 
('2014-01-13T08:46:00',5), 
('2014-01-13T08:50:00',4) 

;with times as (
    select MIN(stime) as stime,MAX(stime) as etime from @t 
    union all 
    select DATEADD(minute,1,stime),etime from times where stime < etime 
) 
select 
    t.stime,t_1.svalue 
from 
    times t 
     left join 
    @t t_1 
     on 
      t.stime >= t_1.stime --Find an earlier or equal row 
     left join 
    @t t_2 
     on 
      t.stime >= t_2.stime and --Find an earlier or equal row 
      t_2.stime > t_1.stime --That's a better match than t_1 
where 
    t_2.stime is null --Second join fails 
order by t.stime 
option (maxrecursion 0) 

我们创建了一个名为CTE是times找出所有的最小值和最大值stime值之间的分钟。然后,我们尝试将两个连接返回到原始表,并使用注释指出这两个连接尝试查找的内容。然后,我们在WHERE子句中删除任何连接成功的行,这些行是t_1连接找到表中匹配最佳行的确切行。

option (maxrecursion 0)只是为了允许CTE与更广泛的输入值一起使用,其中生成所有stime值可能需要大量的递归。