I've been trying to get the number of weekend days (Saturday and Sunday) between 2 given dates.
I came across this solution: http://crossedlogic.blogspot.ca/2008/09/using-sql-to-find-work-days-in-date.html
When I call the function, it returns OK as message in the output, I want it to return the count of weekend days instead.
What am I doing wrong?
Code:
DROP FUNCTION IF EXISTS `fn_GET_WEEKEND_DAYS`;
DELIMITER $$
CREATE FUNCTION `fn_GET_WEEKEND_DAYS`(StartDate DATE, EndDate DATE) RETURNS INT
BEGIN
# declare the variables.
DECLARE varDays INT;
# create the temprorary table to insert the data in.
CREATE TEMPORARY TABLE temp(calendarDate DATE, isWeekend TINYINT(1));
# insert the starting date.
INSERT INTO temp VALUES(StartDate, NULL);
# insert each day by increment of 1 day untill reached the end date.
WHILE (SELECT MAX(CalendarDate) FROM temp) < EndDate DO
INSERT INTO temp
SELECT ADDDATE(MAX(CalendarDate), INTERVAL 1 DAY), NULL
FROM temp;
END WHILE;
# update the is weekend field depending if the day of week of each row is 1 or 7. (saturday or sunday)
UPDATE temp SET isWeekend = CASE WHEN DAYOFWEEK(calendarDate) IN (1, 7) THEN true ELSE false END;
# count the date that are weekends.
SELECT COUNT(calendarDate) INTO varDays FROM temp WHERE isWeekend = true;
# drop the temp table.
DROP TEMPORARY TABLE IF EXISTS temp;
RETURN varDays;
END $$
TEST:
SELECT fn_GET_WEEKEND_DAYS(CURDATE(), ADDDATE(CURDATE(), INTERVAL 10 DAY)) AS TEST;
any help and advice would be greatly appreciated.
Quick fix of your current solution:-
DROP FUNCTION IF EXISTS `fn_GET_WEEKEND_DAYS`;
DELIMITER $$
CREATE FUNCTION `fn_GET_WEEKEND_DAYS`(StartDate DATE, EndDate DATE) RETURNS INT
BEGIN
# declare the variables.
DECLARE varDays INT;
DECLARE varDate DATE;
IF (StartDate > EndDate) THEN
SET varDate = StartDate;
SET StartDate = EndDate;
SET EndDate = varDate;
END IF;
# create the temprorary table to insert the data in.
CREATE TEMPORARY TABLE temp1(calendarDate DATE, isWeekend TINYINT(1));
# insert the starting date.
INSERT INTO temp1 VALUES(StartDate, NULL);
# insert each day by increment of 1 day untill reached the end date.
SET varDate = StartDate;
WHILE varDate < EndDate DO
INSERT INTO temp1 VALUES(ADDDATE(varDate, INTERVAL 1 DAY), NULL);
SELECT MAX(CalendarDate) INTO varDate FROM temp1;
END WHILE;
# update the is weekend field depending if the day of week of each row is 0 or 1. (saturday or sunday)
UPDATE temp1 SET isWeekend = CASE WHEN DAYOFWEEK(calendarDate) = 7 OR DAYOFWEEK(calendarDate) = 1 THEN true ELSE false END;
# count the date that are weekends.
SELECT COUNT(calendarDate) INTO varDays FROM temp1 WHERE isWeekend = true;
# drop the temp1 table.
DROP TEMPORARY TABLE IF EXISTS temp1;
RETURN varDays;
END $$
Big problem was that it was using temp tables, and trying to insert into a temp table based on a select from that temp table which cannot be done. It would give the error You cannot refer to a TEMPORARY table more than once in the same query. For example, the following does not work:
If you have a limited range of dates then probably easy enough to do in single SQL statement
EDIT
A way of doing it with a single SQL statement, copying with a max total date range of 9999 days:-
SELECT SUM(IF(DAYOFWEEK(DATE_ADD('2014-05-02', INTERVAL units.aCnt + tens.aCnt * 10 + hundreds.aCnt * 100 + thousands.aCnt * 1000 DAY) ) IN (1,7), 1, 0))
FROM (SELECT 1 AS aCnt UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 0) units
CROSS JOIN (SELECT 1 AS aCnt UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 0) tens
CROSS JOIN (SELECT 1 AS aCnt UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 0) hundreds
CROSS JOIN (SELECT 1 AS aCnt UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 0) thousands
WHERE '2017-03-01' >= DATE_ADD('2014-05-02', INTERVAL units.aCnt + tens.aCnt * 10 + hundreds.aCnt * 100 + thousands.aCnt * 1000 DAY)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.