Reputation: 696
This is a Mysql/sql query question but allow me to explain the context: I would like to equip my PHP calendar with a '< PREV' and 'NEXT >' button allowing a user to easily go to the previous or next available month that has DATABASE ENTRIES AVAILABLE. If there are no database entries available, I want to disable the button (I never want the system to present an empty calendar).
Example: User has FEB in view. JAN and MAR do not contain entries but DEC and APR do. The 'NEXT >' button then needs to switch to the April calendar. The '< PREV' button needs to switch to the December calendar.
So basically I'm looking for a single efficient query that can check if entries exist prior to and after (but not part of) the month in view.
The table has a field 'logDate' which is of type date 'Y-m-d'.
I started fumbling with the following query to check first whether or not a date exists before and after the given date but I understand that there are some things wrong with this query. For one, if there's an entry in the table for '2013-03-19' my query will spit out a 1 for prev - which of course doesn't indicate if an entry exists for months prior to March.
SELECT IF( EXISTS(SELECT dayId FROM LogbookDay
WHERE logDate < '2013-03-20' AND userId = 2), 1, 0) as prev,
IF( EXISTS(SELECT dayId FROM LogBookDay WHERE logDate > '2013-03-20'
AND userId = 2), 1, 0) as next
Upvotes: 1
Views: 6125
Reputation: 4414
Modify the start date to the beginning and end of the month: For prev, you modify to the first day of the month, by subtracting 1 less than the current day of the month. For next, you do the same, then add 1 month:
SELECT
(SELECT dayId FROM LogbookDay WHERE
logDate < ADDDDATE('2013-03-20', 1-DAY('2013-03-20')) AND userId = 2
ORDER BY logDate DESC LIMIT 1
) as PREV,
(SELECT dayId FROM LogBookDay WHERE
logDate >= ADDDATE(ADDDDATE('2013-03-20', 1-DAY('2013-03-20')), INTERVAL 1 MONTH) AND userId = 2
ORDER BY logDate ASC LIMIT 1
) as NEXT
(Or, do this in PHP, as it's likely to result in more readable code.)
Display the link differently depending on if the result is a null or a date.
It might be more elegant if you were pulling a date instead of an ID:
SELECT
(SELECT MAX(logDate) FROM LogbookDay WHERE
logDate < ADDDDATE('2013-03-20', 1-DAY('2013-03-20')) AND userId = 2
) as PREV,
(SELECT MIN(logDate) FROM LogBookDay WHERE
logDate >= ADDDATE(ADDDDATE('2013-03-20', 1-DAY('2013-03-20')), INTERVAL 1 MONTH) AND userId = 2
) as NEXT
But that depends on exactly what you're doing with the information you find. If all you're doing is creating a link to a new month, pulling the nearest date not in the same month should do the trick.
Upvotes: 4
Reputation: 696
With my own query and a pointer from one of the posted answers I have been able to come up with a simple query that checks whether or not entries exist with months prior and after to the month currently in view.
Assuming month in view is March 2013:
SELECT IF( EXISTS(SELECT dayId FROM LogBookDay
WHERE logDate < '2012-03-01' AND userId = 1), 1, 0) as prev,
IF( EXISTS(SELECT dayId FROM LogBookDay
WHERE logDate > CONCAT('2012-03-',LAST_DAY('2003-02-05'))
AND userId = 1), 1, 0) as next
Upvotes: 1
Reputation: 1637
SELECT
if(min(logDate) < '2013-03-20', 1, 0) 'NEXT',
if(max(logDate) > '2013-03-20', 1, 0) 'PAST'
FROM LogbookDay
WHERE logDate < '2013-03-20' AND logDate > '2013-03-02'
AND userId = 2
Upvotes: 0