2011-01-19 48 views
6

我有一個數據表,我想通過存儲過程選擇出來,以便用戶可以連接MS Excel的前端,並使用原始數據作爲源圖表。生成連續日期到左外部連接的SQL臨時表到

表中原始數據的問題是日期中存在差距,因爲如果某一天沒有數據(沒有該日期的記錄),那麼當用戶嘗試繪製它時會產生問題。

我也想將我的存儲過程更新到左外連接到一個臨時日期表中,這樣右側就會出現空位,我可以將它們轉換爲零,以便他們擁有簡單的繪圖體驗。

我該如何最好地生成一個開始和結束日期之間的日期字段表?

+0

你正在尋找一個序列發生器; [this](http://msdn.microsoft.com/en-us/library/aa175802(v = sql.80).aspx)是我用於上次需要基礎的文章。雖然,當然,如果你只是想做一次,光標或簡單的循環會做得很好... – 2011-01-19 16:03:10

回答

12

在SQL Server 2005和了,你可以使用這樣的事情(公用表表達式CTE)要做到這一點:

DECLARE @DateFrom DATETIME 
SET @DateFrom = '2011-01-01' 

DECLARE @DateTo DATETIME 
SET @DateTo = '2011-01-10' 

;WITH DateRanges AS 
(
    SELECT @DateFrom AS 'DateValue' 
    UNION ALL 
    SELECT DATEADD(DAY, 1, DateValue) 
    FROM DateRanges 
    WHERE DateValue < @DateTo 
) 
SELECT * FROM DateRanges 

你可以LEFT OUTER JOIN這CTE對你的表並返回結果。

+0

終於!這次真是萬分感謝。這似乎應該是如此簡單,但其他所有答案都涉及到創建函數或永久表的非常類似的問題。這正是我需要的解決方案,並且完美地工作。 – 2013-06-19 21:35:01

+0

這是更簡單的方法,但是如果它增長到數千或數百萬個日期,則與暫時或永久表相比,它的性能較差。檢查了這一點:http://www.sqlservercentral.com/articles/T-SQL/74118/ – 2013-11-04 14:59:32

4

一種方法是用一個CTE:

with cte_dates as (
    select cast('20110119' as datetime) as [date] 
    union all 
    select dateadd(dd, 1, [date]) 
     from cte_dates 
     where dateadd(dd, 1, [date]) <= '20111231' 
) 
select [date], YourColumn 
    from cte_dates 
     left join YourTable 
      on ... 
option (maxrecursion 0); 
+0

+1因爲您的帖子是在接受答案的確切分鐘提交的,並且因爲您的WHERE子句比他的(它適用於大於1的間隔,這在接受的答案中被忽略)。 – kmote 2015-08-06 15:41:03

4

另一種方式來做到這一點是具有存儲表。它不會像上面的一些解決方案那樣由於遞歸限制而窒息。

DECLARE @dates AS TABLE ([Date] date); 

DECLARE @date date = {d '2010-10-01'}; 
DECLARE @endDate date = {d '2010-11-01'}; 

while (@date < @endDate) 
BEGIN 
    INSERT INTO @dates VALUES (@date); 
    SET @date = dateadd(DAY, 1, @date) 
END 
SELECT * FROM @dates; 

SQL Fiddle