在两个日期之间显示所有日期数据;如果特定日期不存在行,则在所有列中显示零

时间:2012-10-15 07:23:00

标签: sql sql-server tsql

我想显示两个日期之间的所有日期,当有任何日期数据缺失时,它应该在val列中显示为零。

declare @temp table (
id int identity(1,1) not null,
CDate smalldatetime ,
val int
)

插入要检查的数据的语句

insert into @temp select '10/2/2012',1
insert into @temp select '10/3/2012',1
insert into @temp select '10/5/2012',1
insert into @temp select '10/7/2012',2
insert into @temp select '10/9/2012',2
insert into @temp select '10/10/2012',2
insert into @temp select '10/13/2012',2
insert into @temp select '10/15/2012',2

在每月的第一天和今天之间检索记录

select * from @temp where CDate between '10/01/2012' AND '10/15/2012'

当我运行此查询时,它会显示这两个日期之间的所有数据,但我还要包含val=0

的缺少日期

SQL FIDDLE WITH SAMPLE DATA

6 个答案:

答案 0 :(得分:10)

;with d(date) as (
  select cast('10/01/2012' as datetime)
  union all
  select date+1
  from d
  where date < '10/15/2012'
  )
select t.ID, d.date CDate, isnull(t.val, 0) val
from d
left join temp t
       on t.CDate = d.date
order by d.date
OPTION (MAXRECURSION 0) -- use this if your dates are >99 days apart

你需要弥补日期,所以我在这里使用递归公用表表达式。 SQL Fiddle

  

MAXRECURSION编号

     

指定此查询允许的最大递归数。数字是非负数    0到32767之间的整数。指定0时,不应用限制。如果是这个选项    未指定,服务器的默认限制为100。

     

在查询期间达到MAXRECURSION限制的指定或默认数量时    执行,查询结束并返回错误。

答案 1 :(得分:3)

只要从日期到日期之间的时间少于2047天,这将有效。

declare @from smalldatetime = '10/01/2012'
declare @to smalldatetime = '10/15/2012'

select t.id, dateadd(day, number,@from), isnull(val, 0) val from @temp t
right join master..spt_values s
on dateadd(d, s.number, @from) = t.CDate
where
datediff(day, @from, @to ) > s.number
and s.type = 'P'

答案 2 :(得分:2)

我认为最好的方法是创建自己的日期表(你也可以使用master.dbo.spt_values,但我个人不喜欢这个解决方案)

declare @Temp_Dates table (CDate datetime)
declare @Date datetime
select @Date = (select min(CDate) from temp)

while @Date <= (select max(CDate) from temp)
begin
    insert into @Temp_Dates (CDate)
    select @Date

    select @Date = dateadd(dd, 1, @Date)
end

select D.CDate, isnull(T.id, 0) as id
from @Temp_Dates as D
    left outer join temp as T on T.CDate = D.CDate

你也可以使用CTE的递归解决方案

答案 3 :(得分:2)

DECLARE @min DATETIME, 
        @max DATETIME, 
        @val INT 

SELECT @min = Min(CDATE), 
       @max = Max(CDATE) 
FROM   TEMP 

DECLARE @temp TABLE 
  ( 
     CDATE SMALLDATETIME, 
     VAL   INT 
  ) 

WHILE @min < @max 
  BEGIN 
      SELECT @val = VAL 
      FROM   TEMP 
      WHERE  CDATE = @min 

      INSERT @temp 
      VALUES (@min, 
              @val) 

      SET @min = Dateadd(D, 1, @min) 
      SET @val = 0 
  END 

SELECT * 
FROM   @temp 

答案 4 :(得分:1)

Declare @temp Table(id int identity(1,1) not null,CDate smalldatetime ,val int)
insert into @temp select '10/2/2012',1
insert into @temp select '10/3/2012',1
insert into @temp select '10/5/2012',1
insert into @temp select '10/7/2012',2
insert into @temp select '10/9/2012',2
insert into @temp select '10/10/2012',2
insert into @temp select '10/13/2012',2
insert into @temp select '10/15/2012',2

DECLARE @startDate DATE= '10/01/2012'
DECLARE @endDate DATE= '10/15/2012'

SELECT t.Id, X.[Date],Val = COALESCE(t.val,0)
FROM 
    (SELECT [Date] = DATEADD(Day,Number,@startDate)  
    FROM  master..spt_values  
    WHERE Type='P' 
    AND DATEADD(day,Number,@startDate) <= @endDate)X
LEFT JOIN  @temp t 
ON X.[Date] = t.CDate

enter image description here

答案 5 :(得分:0)

使用带有min和max的递归cte

declare @T table (id int identity(1,1) primary key, dt date not null, val int not null);
insert into @T (dt, val) values 
       ('10/2/2012',1)
     , ('10/3/2012',1)
     , ('10/5/2012',1)
     , ('10/7/2012',2)
     , ('10/9/2012',2)
     , ('10/10/2012',2)
     , ('10/13/2012',2)
     , ('10/15/2012',2);
--select * from @T;
with cte as 
( select min(dt) as dt, max(dt) as mx 
  from @T 
  union all 
  select dateadd(dd, 1, dt), mx 
  from CTE 
  where dt < mx
)
select c.dt, isnull(t.val, 0) as val 
from cte c
left join @T t
on c.dt = t.dt
order by c.dt
option (maxrecursion 0);

dt         val
---------- -----------
2012-10-02 1
2012-10-03 1
2012-10-04 0
2012-10-05 1
2012-10-06 0
2012-10-07 2
2012-10-08 0
2012-10-09 2
2012-10-10 2
2012-10-11 0
2012-10-12 0
2012-10-13 2
2012-10-14 0
2012-10-15 2