2012-10-15 27 views
5

Tôi muốn hiển thị tất cả các ngày giữa hai ngày khi có bất kỳ dữ liệu ngày nào bị thiếu thì sẽ hiển thị số không trong cột val.HIỂN THỊ TẤT CẢ Ngày dữ liệu giữa hai ngày; nếu không có hàng tồn tại cho ngày cụ thể thì hiển thị số không trong tất cả các cột

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

INSERT BÁO CÁO CHO DỮ LIỆU ĐỂ KIỂM TRA

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 

Lấy hồ sơ giữa ngày đầu tiên của tháng và ngày nay

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

Như tôi chạy truy vấn này của nó cho tôi tất cả dữ liệu giữa hai ngày này nhưng tôi cũng muốn bao gồm các ngày bị thiếu với val=0

SQL FIDDLE WITH SAMPLE DATA

Trả lời

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 

Bạn cần phải tạo ngày tháng, vì vậy tôi đã sử dụng biểu thức bảng chung đệ quy ở đây. SQL Fiddle

số MAXRECURSION

Chỉ định số lượng tối đa cho phép recursions cho truy vấn này. số là số nguyên không hợp lệ giữa 0 và 32767. Khi được chỉ định 0, không có giới hạn nào được áp dụng. Nếu tùy chọn này là không được chỉ định, giới hạn mặc định cho máy chủ là 100.

Khi số được chỉ định hoặc mặc định cho giới hạn MAXRECURSION đạt được trong truy vấn thực hiện, truy vấn được kết thúc và lỗi được trả về.

+0

thay vì làm ngày chúng ta có thể làm điều gì đó trong mệnh đề where ... tôi nghĩ rằng chúng ta cũng có thể sử dụng! (NOT) nhà điều hành để tìm ngày mất tích và có thể công đoàn hai - một cho ngày và khác cho ngày thiếu – rahularyansharma

+1

Bạn sẽ cần phải có được ngày từ SOMEWHERE, vậy tại sao không làm cho họ? Có phạm vi ngày ở 2 vị trí trong CTE không khác với mệnh đề WHERE. – RichardTheKiwi

+0

@rahularyansharma, nếu bạn có câu trả lời, hãy đưa câu trả lời vào câu hỏi? – Jodrell

2

Tôi nghĩ rằng cách tốt nhất để làm điều này là để tạo ra bảng của riêng bạn với số ngày (bạn cũng có thể sử dụng master.dbo.spt_values, nhưng cá nhân tôi không thích giải pháp mà)

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 

bạn cũng có thể sử dụng giải pháp đệ quy với CTE

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 
3

này sẽ làm việc càng lâu càng có ít hơn 2047 ngày giữa từ và đến ngày

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

Tôi sẽ tư vấn cho giải pháp này. spt_values ​​ở chế độ chính, vì vậy có thể có các mối lo ngại về bảo mật trong môi trường sản xuất. Ngoài ra spt_values ​​không phải là tài liệu hoặc hỗ trợ do đó không có đảm bảo nó sẽ vẫn không thay đổi trong phiên bản tương lai. – Tobsey

+0

@Tobsey là bạn đang trolling? Điều này được sử dụng ở mọi nơi. Nó sẽ không bao giờ được gỡ bỏ từ ms-sql và không có vấn đề an ninh truy cập vào bảng –

+1

Không, tôi không phải là trolling. spt_values ​​được sử dụng bởi các thủ tục và chức năng SQL Server nội bộ và không được tài liệu hoặc được hỗ trợ cho mã tùy chỉnh. Có các phương thức được hỗ trợ khác, chẳng hạn như CTE đệ quy hoặc thậm chí cả dữ liệu tĩnh thuần túy cũ trong bảng để đạt được mục tiêu này. Tôi muốn đi với các giải pháp được tài liệu và hỗ trợ. Chỉnh sửa xem tại đây để biết cấu hình bảo mật sẽ phá vỡ giải pháp của bạn http://support.microsoft.com/kb/75291 – Tobsey

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

Các vấn đề liên quan