如何计算周,包括从MySQL季度开始的部分周



我想在MySQL中计算一个季度的周数。

不幸的是,所有现有的解决方案都是基于两个日期之间的DATEDIFF,这不是我想要的。

例如,今天的日期是2月24日。本季度为第9周,因为1月的前三天(本年度为星期五、星期六和星期日)为第1周。

如果我做一个DateDiff并简单地除以7,它仍然只给我以天为单位的总周数。它没有给出本季度开始以来的日历周数。

CEIL(DATEDIFF(CURDATE(), MAKEDATE(YEAR(CURDATE()), 2) + INTERVAL QUARTER(CURDATE()) QUARTER  - INTERVAL 1 QUARTER) /7) AS WEEK_IN_QUARTER,

这给了我第8周,期望(想要的)输出是9。

在一周中加上1将会导致问题,当情况相反时,或者当一个季度只剩下部分周时,或者当我们进入任何一周的第4天时。

第一周从季度的第一天开始,到当周的周日结束。我已经使用了MySQL的每一个DATE函数,我真的卡住了。

我通常使用Python在客户端执行此操作(见下文),但我想知道在尝试翻译此内容之前是否有一种简单的方法在MySQL中执行此操作。如有任何帮助,不胜感激。

Python代码,如果它使我想说的更清楚一点:

from datetime import timedelta, date
from dateutil import relativedelta
NEXT_MONDAY = relativedelta.relativedelta(weekday=relativedelta.MO)
LAST_MONDAY = relativedelta.relativedelta(weekday=relativedelta.MO(-1))
ONE_WEEK = timedelta(weeks=1)
def get_week_in_quarter(dt):
d: date = dt.date()
year = d.year
# Q0 = January 1, Q1 = April 1, Q2 = July 1, Q3 = October 1
quarter = ((d.month - 1) // 3)
quarter_start = date(year, (quarter * 3) + 1, 1)
quarter_week_2_monday = quarter_start + NEXT_MONDAY
if d < quarter_week_2_monday:
week = 1
else:
cur_week_monday = d + LAST_MONDAY
week = int((cur_week_monday - quarter_week_2_monday) / ONE_WEEK) + 2
if quarter == 0:
year -= 1
quarter = 4
return week

编辑1:为了进一步澄清,如果我在一个过渡日(今天是)把周和天分开,您可以看到问题:

SET @day1=DATE(CURDATE());
SET @day2=DATE(MAKEDATE(YEAR(CURDATE()), 2) + INTERVAL QUARTER(CURDATE()) QUARTER  - INTERVAL 1 QUARTER);
SELECT CONCAT(SUBSTRING_INDEX(CEIL(DATEDIFF(@day1,@day2)/7),'.',1),'Weeks ',
SUBSTRING_INDEX(ABS(DATEDIFF(@day1,@day2)),'.',1)-SUBSTRING_INDEX(ROUND(DATEDIFF(@day1,@day2))/7,'.',1)*7,'Days'
)AS WEEKINQUARTER

输出如下:8周4天

我不知道如何通过将天数差除以7来产生所需的输出(只是&;9&;)。在Python中,我必须设置一个delta到最后一个星期一来解释这个。我不知道如何在MySQL中做到这一点。

编辑2草莓的答案下面解决了这个问题,我在SQL。我最终使用CEIL而不是地板,但对于任何在未来寻找当前财政季度周计算SQL的人来说,这是一个解决方案:

这样行吗?

SELECT FLOOR(DATEDIFF('2021-02-24',CONCAT(DATE_FORMAT(LAST_DAY(MAKEDATE(EXTRACT(YEAR FROM '2021-02-24'),1) + INTERVAL QUARTER('2021-02-24')*3-3 MONTH),'%Y-%m-'),'01') - INTERVAL WEEKDAY(CONCAT(DATE_FORMAT(LAST_DAY(MAKEDATE(EXTRACT(YEAR FROM '2021-02-24'),1) + INTERVAL QUARTER('2021-02-24')*3-3 MONTH),'%Y-%m-'),'01')) DAY)/7) x;

模式3week()是ISO周,这是我认为你想要的。
你可以用算术计算出每季度的星期。前13周为Q1, 14-26周为Q2, 27-39周为Q3,其余为Q4。

:

select (case when week(date, 3) <= 13 then week(date, 3)
when week(date, 3) <= 26 then week(date, 3) - 13
when week(date, 3) <= 39 then week(date, 3) - 26
else week(date, 3) - 39
end)

你可以使用一些技巧来使用模运算来简化它,但我认为这是最清楚的解释该怎么做。

最新更新