Đề xuất đầu tiên của tôi là sử dụng bảng lịch của bạn, nếu bạn chưa có, hãy tạo một bảng. Chúng rất hữu ích. Sau đó, truy vấn của bạn đơn giản như sau:
DECLARE @MinDate DATE = '20140101',
@MaxDate DATE = '20140106';
SELECT Date
FROM dbo.Calendar
WHERE Date >= @MinDate
AND Date < @MaxDate;
Nếu bạn không muốn hoặc không thể tạo bảng lịch, bạn vẫn có thể thực hiện việc này nhanh chóng mà không cần CTE đệ quy:
DECLARE @MinDate DATE = '20140101',
@MaxDate DATE = '20140106';
SELECT TOP (DATEDIFF(DAY, @MinDate, @MaxDate) + 1)
Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @MinDate)
FROM sys.all_objects a
CROSS JOIN sys.all_objects b;
Để đọc thêm về điều này, hãy xem:
- Tạo một tập hợp hoặc chuỗi không có vòng lặp - phần 1
- Tạo một tập hợp hoặc chuỗi không có vòng lặp - phần 2
- Tạo một tập hợp hoặc chuỗi không có vòng lặp - phần 3
Liên quan đến việc sử dụng chuỗi ngày này trong con trỏ, tôi thực sự khuyên bạn nên tìm một cách khác. Thường có một giải pháp thay thế dựa trên tập hợp sẽ hoạt động tốt hơn nhiều.
Vì vậy, với dữ liệu của bạn:
date | it_cd | qty
24-04-14 | i-1 | 10
26-04-14 | i-1 | 20
Để nhận được số lượng vào ngày 28-04-2014 (mà tôi thu thập là yêu cầu của bạn), bạn thực sự không cần bất kỳ điều nào ở trên, bạn có thể chỉ cần sử dụng:
SELECT TOP 1 date, it_cd, qty
FROM T
WHERE it_cd = 'i-1'
AND Date <= '20140428'
ORDER BY Date DESC;
Nếu bạn không muốn nó cho một mục cụ thể:
SELECT date, it_cd, qty
FROM ( SELECT date,
it_cd,
qty,
RowNumber = ROW_NUMBER() OVER(PARTITION BY ic_id
ORDER BY date DESC)
FROM T
WHERE Date <= '20140428'
) T
WHERE RowNumber = 1;