To determine if any part of the date range falls within the year and month in
question try this:
SELECT *
FROM YourTable
WHERE (YEAR(beginningdate ) = [Enter Year:]
AND MONTH(beginningdate ) = [Enter Month:])
OR (YEAR(endingdate) = [Enter Year:]
AND MONTH(endingdate) = [Enter Month:])
OR (DATESERIAL([Enter Year:],EnterMonth:],1)
BETWEEN beginningdate AND endingdate)
OR (DATESERIAL([Enter Year:],EnterMonth:]+1,0)
BETWEEN beginningdate AND endingdate);
The month should be entered as a number at the parameter prompt, 1 for
January, 2 for February etc. The query looks at four possible scenarios:
1. The beginningdate is in the year and month in question.
2. The endingdate is in the year and month in question.
3. The first day of the month in question falls between the beginning and
ending dates.
4. The last day of the month in question falls between the beginning and
ending dates.
If any of these are true then the row will be returned.
To count the number of occupancy nights grouped by month the trick is to
first create a Calendar table, which is simply a table of all dates over a
given period, 10 years say, in a column caldate. An easy way to create the
table is to serially fill down a column in Excel with the dates and import
the worksheet into Access as a table. It can also be done completely within
Access itself with some VBA code which I can post here if you wish.
You can then join your table to the Calendar table in a query like so:
SELECT
ClientID,
YEAR(caldate) AS YearOccupied,
MONTH(caldate) As MonthOccupied,
COUNT(*) AS NightsOccupied
FROM YourTable, Calendar
WHERE caldate BETWEEN beginningdate AND endingdate-1
GROUP BY ClientID, YEAR(calDate), MONTH(calDate);
Because the endingdate is not a bednight, the last bednight in your example
being 4 March, one is subtracted from the endingdate when defining the range
for the join criterion in the query's WHERE clause. If you are wondering why
the join is done in the WHERE clause rather than a JOIN clause its because
the BETWEEN….AND operator does not work in a JOIN clause. The query could be
written with a JOIN clause but it would be necessary to use >= and <=
operations, which will work in a JOIN clause.
BTW its very important when working with date ranges in this way that the
date/time values in the table do not have a non-zero time of day. If the
dates have been entered manually as dates this will be the case, but
sometimes people mistakenly use the Now() function to automatically insert a
date into a table, which results in a date with the current time of day being
entered, which may not be readily apparent if the values are formatted as a
date. To automatically insert a date into a table the Date() function should
be used. This inserts a date with a zero time of day, there being no such
thing in Access a date without a time of day or vice versa when the date/time
data type is used.
I haven't tested the two queries, but I think I've got the logic right.
Ken Sheridan
Stafford, England