MySQL finds the last Friday of every month-function definition and use

One question for database homework looks like this:

There is a table named emp that records employee information, and the following field HIREDATE indicates the date the employee was hired:

Insert picture description here

Then the question is this:

q7.	Show details of employee hiredates and the date of their first payday. 
(Paydays occur on the last Friday of each month) 
(plus their names)

This means that the last Friday of every month is the day when wages are paid, and we are required to export the day when they receive the first pot of gold. (Here is actually calculating the payday of the current month, regardless of the situation where hiredate exceeds payday)

So how to calculate the last Friday of the month from a date? We use the most violent method, direct iterative calculation:

Ideas:

  1. LAST_DAY function finds the last day of the month x
  2. Date x decreases day by day
  3. Until x equals Friday, which is the last Friday

Code:

DELIMITER $$	# 结束符由 ; 改为 $$ 。因为函数中间需要用到 ; 号
DROP FUNCTION IF EXISTS last_friday $$	# 删除之前定义的函数 last_friday 
CREATE FUNCTION last_friday (dt DATE) RETURNS DATE	# 定义函数 last_friday 有一个DATE类的形参 dt,返回DATE对象
BEGIN
	DECLARE last DATE;	# 临时变量 last
	SET last=LAST_DAY(dt);	# last=dt的最后一天
	WHILE DATE_FORMAT(last, "%W")!="Friday" DO	# 不断判断是否为周五
		SET last=DATE_SUB(last, interval 1 day);	# 迭代减少天数
	END WHILE;
	RETURN last;	# 返回结果
END $$
DELIMITER ;	# 结束符由 $$ 改为 ; 号 

# 不带注释 ↓

DELIMITER $$
DROP FUNCTION IF EXISTS last_friday $$
CREATE FUNCTION last_friday (dt DATE) RETURNS DATE
BEGIN
	DECLARE last DATE;
	SET last=LAST_DAY(dt);
	WHILE DATE_FORMAT(last, "%W")!="Friday" DO
		SET last=DATE_SUB(last, interval 1 day);
	END WHILE;
	RETURN last;
END $$
DELIMITER ;

Then we can query through the last_friday function:

SELECT ENAME, HIREDATE, last_friday(HIREDATE) FROM emp;

result:

Insert picture description here

Then the next question:

q8.	Refine your answer to 7 such that it works 
even if an employee is hired after the last Friday of the month 
(cf Martin)

It means that some employees joined after payday, such as:

Insert picture description here
Then we should find the next payday. The idea is also very simple, just use the if statement to judge.

  1. If it is 当月paydaygreater 入职日期hiredate, return the payday of the current month
  2. If 当月paydayless than 入职日期hiredate, return the payday of the next month

We first write a function next_friday to calculate the payday of the next month :

DELIMITER $$
DROP FUNCTION IF EXISTS next_friday $$
CREATE FUNCTION next_friday (dt DATE) RETURNS DATE
BEGIN
	DECLARE last DATE;
	SET last=LAST_DAY(DATE_ADD(dt, interval 1 month));
	WHILE DATE_FORMAT(last, "%W")!="Friday" DO
		SET last=DATE_SUB(last, interval 1 day);
	END WHILE;
	RETURN last;
END $$
DELIMITER ;

This function is the same as last_friday, it just calculates the next month:

Insert picture description here

Then we modify last_friday and add a judgment when we return:

DELIMITER $$
DROP FUNCTION IF EXISTS last_friday $$
CREATE FUNCTION last_friday (dt DATE) RETURNS DATE
BEGIN
	DECLARE last DATE;
	SET last=LAST_DAY(dt);
	WHILE DATE_FORMAT(last, "%W")!="Friday" DO
		SET last=DATE_SUB(last, interval 1 day);
	END WHILE;
	RETURN IF(last>dt, last, next_friday(dt));
END $$
DELIMITER ;

Pay attention to this if expression:

if(expr, case1, case2)
if(条件, 情况1, 情况2)

Insert picture description here

Then run the query again:

Insert picture description here

Comfortable

Edit:

The big guys in the comment area provide a more powerful method:

SELECT date_sub(last_day(CURRENT_DATE), interval (dayofweek(last_day(CURRENT_DATE)-6)) day);

The idea is probably:

  1. Select the last day of the month , that islast_day(CURRENT_DATE)

  2. Then look at the day that counts down one week from the last day, which islast_day(CURRENT_DATE)-6

  3. Check the day of the week that counts down from the last day , that is dayofweek(last_day(CURRENT_DATE)-6), the result is in the range of 1-7 (Note: Saturday = 7, Sunday = 1, Monday = 2)

  4. Then subtract this number with the date of the last day to get the date of the last Friday.

Explanation:

Because the solution is for the last Friday, the answer must appear in the range of the last day of the month and the 7 days before it (don’t believe it, count it yourself, you will definitely encounter Friday when you count 7 days ahead):

Insert picture description here

Then we know that today was the day of the week in the previous week, such as Thursday, which means that we count 6 days in the future (to reach the today of the previous week, that is, Thursday), and one day ahead is Friday.

We have counted 6-1 = 5 days later and we can get the correct answer.

Notice that we count 5 days from Thursday, 6 days from Friday, 7 days from Saturday, and 1 day from Sunday. . . . And so on, so the return value of weekofday just conforms to this rule, so there is the following expression:

SELECT date_sub(last_day(CURRENT_DATE), interval (dayofweek(last_day(CURRENT_DATE)-6)) day);

Icon:

Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_44176696/article/details/109010704