2013-11-01 48 views
0

有人可以引导我正确的方向来解决与基于集合的解决方案与基于游标的问题?基于集合的解决方案处理SQL表中的行

给定一个表具有以下行:

 
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 

任何意见和/或方向将不胜感激。

回答

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 
+0

我是能够使这项工作对我的需要。谢谢! – DarLom

+0

当你看一个日期范围“15/12/2012”到“14/01/2013”​​时会发生什么? – bendataclear

+0

@ben很有意思。根据权利,它应该在最大和最小日期上进行DateDiff,并从最小值开始添加日期。我会考虑更新我的帖子。 –

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 
1

另一种解决方案,不知道如何比较这两个已经发布业绩明智的,但它是一个有点更简洁:

使用一个数字表:

Linky

查询:

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

相关问题