Ще хвърля шапката си на ринга с още един подход:
Редактиране: С малко закъснение разбирам, че въпросната функция на Oracle приема низ като втори аргумент и така това не отговаря точно на изискването. Въпреки това MySQL вече любезно е дефинирал 0 - 6 като понеделник - неделя и така или иначе имам морални възражения срещу използването на низ като аргумент за този тип неща. Низът идва или от потребителско въвеждане или още едно картографиране в код от по-високо ниво между числови и низови стойности. Защо не подадете цяло число? :)
CREATE FUNCTION `fnDayOfWeekGetNext`(
p_date DATE,
p_weekday TINYINT(3)
) RETURNS date
BEGIN
RETURN DATE_ADD(p_date, INTERVAL p_weekday - WEEKDAY(p_date) + (ROUND(WEEKDAY(p_date) / (p_weekday + WEEKDAY(p_date) + 1)) * 7) DAY);
END
За да разделите частта, която определя INTERVAL стойност:
Първата част от уравнението просто получава отместването между посочения ден от седмицата и деня от седмицата на посочената дата:
p_weekday - WEEKDAY(p_date)
Това ще върне положително число, ако p_weekday е по-голямо от WEEKDAY(p_date) и обратно. Ще бъде върната нула, ако са еднакви.
ROUND() сегмент се използва за определяне дали исканият ден от седмицата (p_weekday ) вече се е случило през текущата седмица спрямо датата (p_date ) посочено. И така, като пример...
ROUND(WEEKDAY('2019-01-25') / (6 + WEEKDAY('2019-01-25') + 1))
..връща 0 , указващ тази неделя (6 ) не се е случило тази седмица, тъй като 2019-01-25 е петък. По същия начин...
ROUND(WEEKDAY('2019-01-25') / (2 + WEEKDAY('2019-01-25') + 1))
...връща 1 защото сряда (2 ) вече е минало. Имайте предвид, че това ще върне 0 ако p_weekday е същият като деня от седмицата на p_date .
Тази стойност (или 1 или 0 ) след това се умножава по константата 7 (броя дни в седмицата).
Следователно, ако p_weekday вече се е случило през текущата седмица, то ще добави 7 към отместването p_weekday - WEEKDAY(p_date) , тъй като това отместване би било отрицателно число и ние искаме дата в бъдещето.
Ако p_weekday все още не се е случило през текущата седмица, тогава можем просто да добавим отместването към текущата дата, защото отместването ще бъде положително число. Оттук и секцията ROUND(...) * 7 е равно на нула и по същество се игнорира.
Желанието ми за този подход беше да симулирам IF() състояние математически. Това би било еднакво валидно:
RETURN DATE_ADD(p_date, INTERVAL p_weekday - WEEKDAY(p_date) + IF(p_weekday - WEEKDAY(p_date) < 0, 7, 0) DAY);
И в интерес на обективността, при изпълнение на 1 милион итерации няколко пъти на всяка функция IF -базираната версия беше средно с около 4,2% по-бърза от ROUND -базирана версия.