我想显示两个日期之间的所有日期,当有任何日期数据缺失时,它应该在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
答案 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
答案 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