3

現在、いくつかのデータ テーブルをレポートにまとめようとしています。テーブル内の各レコードは、次のような日付範囲で構成されます。

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

日付範囲が休暇日数のようなものを意味すると仮定すると、1 か月あたりの休暇日数の合計を計算できるようになりたいと考えています。私は、日付範囲が月の境界を越えるときという、エッジケースとは別に動作するように見える DatePart 関数に出くわしました。DatePart 関数は 1 つの特定の日付の月を返すため、2 つの別々の日付に適用されるため、そのエッジ ケース レコード (上記の例ではレコード 3) の休暇日数を決定するためにそれを使用することはできなくなりました。月。

理想的には、最終的なテーブルを次のようにしたい:

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

各レコードが異なる日を示す一時テーブルを作成し、それに対してクエリを実行するなど、いくつかの厄介なオプションを検討しましたが、これがレポートとどのように結びついているかはわかりません. 現在、私のレポート レコード ソースは (正しくない) クエリです。レコード ソースを返す VBA 関数としてレコード ソースを使用することは可能ですか?

私が考えたもう1つのことは、エッジケースを2つの別々のレコードに分割する最初のクエリを作成し、日付範囲が1か月のみをカバーし、それを最終的なグループ化クエリに使用することでした. それは可能ですか?

この問題にはもっと簡単な解決策があるかもしれないと思いますが、まだわかりません。

誰かが何かアイデアを持っていれば、それは大歓迎です!

4

1 に答える 1

2

Access クエリを使用してタスクを実行するには、[Numbers] という名前のテーブルを作成し、[n] という名前の単一の Number (Long Integer) 列を作成する必要があります一緒に働くこと。私は次のように私のものを作成しました

   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-02-01#

DateSerial(2013, 1, 234) = #2013-08-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] として保存しましょう。これを使用して、各日付範囲の個々の日を抽出できます (StartDate を省略して、最終的なカウントが質問のカウントと一致するようにします)。

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
于 2013-05-19T14:02:58.760 に答える