有人可以指导我使用基于集合的解决方案与基于光标的解决方案来解决此问题吗?
给定一个包含以下行的表:
Date Value 2013-11-01 12 2013-11-12 15 2013-11-21 13 2013-12-01 0
我需要一个查询,为2013-11-1和2013-12-1之间的每个日期提供一行,如下所示:
2013-11-01 12 2013-11-02 12 2013-11-03 12 ... 2013-11-12 15 2013-11-13 15 2013-11-14 15 ... 2013-11-21 13 2013-11-21 13 ... 2013-11-30 13 2013-11-31 13
任何建议和/或指示都将受到赞赏。
答案 0 :(得分:1)
我想到的第一件事就是通过查看一年中的某一天来填写缺失的日期。您可以通过加入主数据库中的spt_values表并将数字添加到一年的第一天来完成此操作。
DECLARE @Table AS TABLE(ADate Date, ANumber Int);
INSERT INTO @Table
VALUES
('2013-11-01',12),
('2013-11-12',15),
('2013-11-21',13),
('2013-12-01',0);
SELECT
DateAdd(D, v.number, MinDate) Date
FROM (SELECT number FROM master.dbo.spt_values WHERE name IS NULL) v
INNER JOIN (
SELECT
Min(ADate) MinDate
,DateDiff(D, Min(ADate), Max(ADate)) DaysInSpan
,Year(Min(ADate)) StartYear
FROM @Table
) dates ON v.number BETWEEN 0 AND DaysInSpan - 1
接下来,我将它包装成一个派生表,并添加一个子查询来获取最新的数字。您的最终结果可能类似于:
DECLARE @Table AS TABLE(ADate Date, ANumber Int);
INSERT INTO @Table
VALUES
('2013-11-01',12),
('2013-11-12',15),
('2013-11-21',13),
('2013-12-01',0);
-- Uncomment the following line to see how it behaves when the date range spans a year end
--UPDATE @Table SET ADate = DateAdd(d, 45, ADate)
SELECT
AllDates.Date
,(SELECT TOP 1 ANumber FROM @Table t WHERE t.ADate <= AllDates.Date ORDER BY ADate DESC)
FROM (
SELECT
DateAdd(D, v.number, MinDate) Date
FROM
(SELECT number FROM master.dbo.spt_values WHERE name IS NULL) v
INNER JOIN (
SELECT
Min(ADate) MinDate
,DateDiff(D, Min(ADate), Max(ADate)) DaysInSpan
,Year(Min(ADate)) StartYear
FROM @Table
) dates ON v.number BETWEEN 0 AND DaysInSpan - 1
) AllDates
答案 1 :(得分:1)
另一个解决方案,不确定它与两个已经发布的性能明显相比,但它更简洁:
使用数字表:
<强>查询:强>
DECLARE @SDATE DATETIME
DECLARE @EDATE DATETIME
DECLARE @DAYS INT
SET @SDATE = '2013-11-01'
SET @EDATE = '2013-11-29'
SET @DAYS = DATEDIFF(DAY,@SDATE, @EDATE)
SELECT Num, DATEADD(DAY,N.Num,@SDATE), SUB.[Value]
FROM Numbers N
LEFT JOIN MyTable M ON DATEADD(DAY,N.Num,@SDATE) = M.[Date]
CROSS APPLY (SELECT TOP 1 [Value]
FROM MyTable M2
WHERE [Date] <= DATEADD(DAY,N.Num,@SDATE)
ORDER BY [Date] DESC) SUB
WHERE N.Num <= @DAYS
-
<强> SQL Fiddle 强>
答案 2 :(得分:0)
这是可能的,但既不漂亮也不高效:
除了your_table
之外,您还需要创建第二个表/视图dates
,其中包含您希望在此查询的输出中显示的每个日期。对于您的示例,它至少需要包含2013-11-01到2013-12-01。
SELECT m.date, y.value
FROM your_table y
INNER JOIN (
SELECT md.date, MAX(my.date) AS max_date
FROM dates md
INNER JOIN your_table my ON md.date >= my.date
GROUP BY md.date
) m
ON y.date = m.max_date