2013-11-01 51 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

相關問題