填写缺失值

时间:2014-01-13 07:47:40

标签: sql sql-server

伙计我有这张桌子

+--------------------+------+
|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     |
+--------------------+------+

提前致谢!

4 个答案:

答案 0 :(得分: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

答案 1 :(得分: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)

我们创建了一个名为times的CTE,它可以找到最小和最大stime值之间的所有分钟。然后,我们尝试将两个连接返回到原始表,其中的注释指示这两个连接尝试查找的内容。然后,我们在WHERE子句中消除t_2连接成功的所有行 - 这是t_1连接从表中找到最匹配行的确切行。

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

答案 2 :(得分: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

答案 3 :(得分: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