2013-05-19 19 views
3

我目前正試圖將一些數據表彙總到報告中。表中的每個記錄由一個日期範圍,像這樣的:使用DatePart()以及日期範圍越過日期部分邊界

StartDate EndDate 
-------------------- 
13/04/13  15/04/13 
17/04/13  24/04/13 
28/04/13  03/05/13 
05/05/13  10/05/13 

假設日期範圍意味着像休假的日子裏,我希望能夠計算出每月休假天數的總量。我遇到了DatePart函數,它似乎與一個邊緣情況分開:當日期範圍跨越一個月邊界時。由於DatePart函數返回一個給定日期的月份,因此我不再能夠使用它來確定該邊緣案例記錄的離開的天數(在上面的例子中是記錄3),因爲它適用於兩個單獨的個月。

理想我想我的決賽桌的樣子:

Month  #OfDays 
-------------------- 
    4   11    (1st record - 2, 2nd record - 7, 3rd record - 2) 
    5   8    (3rd record - 3, 4th record - 5) 

我認爲有些凌亂的選項,如填充有每個記錄標誌着不同的一天,然後做在一個查詢的臨時表,但我不確定這與報告有什麼聯繫。現在我的報表記錄源是(錯誤的)查詢,是否有可能將記錄源作爲返回記錄源的VBA函數?

另一件我認爲可能有一個初始查詢,將任何邊緣案例分成兩個單獨的記錄,其中日期範圍只包括一個月,然後將其用於我的最終分組查詢。這甚至可能嗎?

我覺得這個問題可能有一個更簡單的解決方案,但我看不到它。

如果有人有任何想法,將不勝感激!

+0

莫非日期超過一個月的範圍界限:28/04/13至03/06/13? – HansUp

+0

是的,這是一個非常真實的可能性 – rbhalla

回答

2

要使用Access查詢完成您的任務,您將需要創建一個名爲[Numbers]的表,其中包含數字1,2,3 ......的單個Number(Long Integer)列名爲[n]你期望與最合作的一年。我創建了我的如下

n 
---- 
    1 
    2 
    3 
... 
2499 
2500 

您還需要以下VBA函數粘貼到一個接入模塊

Public Function IsValidDayOfYear(YearValue As Long, DayValue As Long) As Boolean 
Dim IsLeapYear As Boolean 
If (YearValue Mod 400) = 0 Then 
    IsLeapYear = True 
ElseIf (YearValue Mod 100) = 0 Then 
    IsLeapYear = False 
ElseIf (YearValue Mod 4) = 0 Then 
    IsLeapYear = True 
Else 
    IsLeapYear = False 
End If 
IsValidDayOfYear = (DayValue <= IIf(IsLeapYear, 366, 365)) 
End Function 

讓我們假設你的源表被稱爲[DateRanges。我們將首先創建一個查詢,該查詢生成源表中每年的每一年的每一天。這裏的技巧是DateSerial() 「軋」 月界限,所以

DateSerial(2013,1,32)=#2013年2月1日#

DateSerial(2013,1,234 )=#2013年8月22日#

SELECT DateSerial(yr.n, 1, dy.n) AS [Date] 
FROM Numbers yr, Numbers dy 
WHERE 
    (
     yr.n 
      BETWEEN (SELECT MIN(DatePart("yyyy", DateRanges.StartDate)) FROM DateRanges) 
       AND (SELECT MAX(DatePart("yyyy", DateRanges.EndDate)) FROM DateRanges) 
    ) 
    AND (dy.n < 367) AND IsValidDayOfYear(yr.n, dy.n) 

爲了您的樣本數據,該查詢返回所有的日子在2013年

讓我們保存了該查詢爲[ALLDAYS。現在,我們可以用它來單獨天提取每個日期範圍(省略起始日期,以便最終計數的問題和你的相符)

SELECT [Date] FROM AllDays 
WHERE EXISTS 
    (
     SELECT * FROM DateRanges 
     WHERE AllDays.[Date] BETWEEN DateAdd("d", 1, DateRanges.StartDate) AND DateRanges.EndDate 
    ) 

返回對應於每個範圍內各天,即,

Date  
---------- 
2013-04-14 
2013-04-15 
2013-04-18 
2013-04-19 
2013-04-20 
2013-04-21 
2013-04-22 
2013-04-23 
2013-04-24 
2013-04-29 
2013-04-30 
2013-05-01 
2013-05-02 
2013-05-03 
2013-05-06 
2013-05-07 
2013-05-08 
2013-05-09 
2013-05-10 

我們可以保存查詢作爲[RangeDays],然後用它按月份來計算我們的數...

SELECT DatePart("m", [Date]) AS [Month], COUNT(*) AS NumOfDays 
FROM RangeDays 
GROUP BY DatePart("m", [Date]) 

...返回

Month NumOfDays 
----- --------- 
    4   11 
    5   8 
+0

令人印象深刻的努力,GT。 +1 – HansUp

+0

@HansUp謝謝。我很確定,我從你身上學到了至少一種技巧。 –

+0

戈爾再次救我!謝謝你的另一個詳細的答案。我是否認爲如果兩個日期範圍交叉,這將不會顯示重複的日期?例如,如果我有01/01/2013-05/01/2013和04/01/2013-10/01/2013,它只會顯示01/01/2013-10/01/2013在[AllDays]查詢? – rbhalla