简体   繁体   English

如何在MySQL查询中获取给定月份的第N个工作日的日期?

[英]How can I get the date of the Nth weekday of a given month in a MySQL query?

I've searched for answers and while I've found similar questions answered online I've been unable to use them for my purpose. 我一直在寻找答案,虽然在网上找到了类似的问题,但仍无法将其用于我的目的。 I need help. 我需要帮助。

I'm building a calendar which supports recurring events. 我正在建立一个支持重复事件的日历。 I'm almost done, but the final piece is the toughest. 我差不多完成了,但是最后一道是最艰难的。 I need to be able to support events that occur on the Nth X of every Y months, where X is a given weekday and Y is a number of months. 我需要能够支持每Y个月的第N个X发生的事件,其中X是给定的工作日,Y是数月。

I've already figured out the "every Y months" part (which is the 2nd to the last line in the query segment below). 我已经弄清楚了“每Y个月”部分(这是下面查询段的第二到最后一行)。 I just need to get the "Nth weekday". 我只需要获取“第N个工作日”即可。

I found a PHP script someone created that claims to solve this wonderfully, and I planned on using it, but then I realized that this must be done entirely within the MySQL query because the values specifying which weekday to get the date for are part of the db record and I cannot get them to use outside of the main query. 我发现有人创建了一个PHP脚本,声称可以很好地解决此问题,并计划使用它,但是后来我意识到,这必须完全在MySQL查询中完成,因为指定获取日期的工作日的值是db记录,我无法在主要查询之外使用它们。

Here's a portion of the query so you can get an idea of where I'm headed with this: 这是查询的一部分,因此您可以了解我的工作方向:

WHEN event_recurring_pattern_type = 'monthly' AND event_recurring_monthly_type = 'dayxofeveryxmonths' THEN
    MOD(PERIOD_DIFF(CONCAT(event_date_year,event_date_month), CONCAT('$date_year','$date_month')), event_recurring_monthly_dayofeveryxmonths) = 0
    AND event_recurring_monthly_dayx = '$date_day'

WHEN event_recurring_pattern_type = 'monthly' AND event_recurring_monthly_type = 'thexweekdayofeveryxmonths' THEN
    MOD(PERIOD_DIFF(CONCAT(event_date_year,event_date_month), CONCAT('$date_year','$date_month')), event_recurring_monthly_dayofeveryxmonths) = 0
    AND '$date_timestamp' = {the date of the Nth weekday of $date_month}

The last line there should compare the calendar's current output date (as it builds the calendar one day at a time) with the date of the Nth weekday of whatever month we're on during the output process. 该行的最后一行应将日历的当前输出日期(因为它一次生成一天的日历)与我们在输出过程中处于哪个月份的第N个工作日的日期进行比较。 When they match up, that event will be output onto the calendar. 当它们匹配时,该事件将输出到日历上。

$date_timestamp is the current output date in 'YYYY-MM-DD' format in this case, so the Nth weekday I get the date for should also be in that format. $ date_timestamp在这种情况下是以'YYYY-MM-DD'格式显示的当前输出日期,因此我得到的第N个工作日的日期也应采用该格式。

If I haven't given enough information, or if this has been adequately answered elsewhere, please let me know. 如果我没有提供足够的信息,或者在其他地方都得到了足够的答复,请告诉我。 One of my previous questions was "closed" because some people thought it was too vague or didn't give enough info, even though I gave plenty of information relevant to my question and still received a perfectly acceptable answer that solved my problem. 我以前的问题之一是“关闭”的,因为有人认为它太模糊或没有提供足够的信息,即使我提供了大量与问题相关的信息,但仍然收到了可以解决我问题的完全可接受的答案。 Give me a chance to improve a question if necessary before performing negative actions. 如果需要,给我机会在执行消极行动之前改善问题。

Thanks in advance. 提前致谢。

Oh yeah, and if this can be further created to optionally get the LAST specified weekday of the given month, that would be even better. 哦,是的,如果可以进一步创建它以有选择地获取给定月份的LAST指定工作日,那就更好了。 The PHP script did that, but like I said, I can't do this with PHP this time. PHP脚本做到了这一点,但是就像我说的那样,这次我无法使用PHP做到这一点。

Use DAYOFWEEK() : 使用DAYOFWEEK()

WHEN event_recurring_pattern_type = 'monthly'
 AND event_recurring_monthly_type = 'thexweekdayofeveryxmonths'
THEN MOD(
       PERIOD_DIFF(
         CONCAT(event_date_year,event_date_month),
         CONCAT('$date_year','$date_month')
       ), event_recurring_monthly_dayofeveryxmonths
     ) = 0
 AND DAYOFWEEK('$date_timestamp') = event_recurring_monthly_dayofweek

The above assumes the addition of the event_recurring_monthly_dayofweek column, but you could just as easily re-use the event_recurring_monthly_dayx column to store the day-of-week integer. 上面假设添加了event_recurring_monthly_dayofweek列,但是您可以轻松地重复使用event_recurring_monthly_dayx列来存储星期几。

The easiest way is to write a program to populate a new table with the information you need. 最简单的方法是编写一个程序,用所需的信息填充新表。 It wouldn't require a very large table to go a long way into the future. 不需要很大的桌子就可以走很长一段路。 Then just join to the table in your query. 然后只需加入查询中的表即可。

I am going to try this (not been proven in the field yet) : 我将尝试此操作(尚未在现场进行验证):

 SET @target = DATE('2013-06-15');
SELECT  1 + ( 
 IF( MONTH(DATE_SUB( @target, INTERVAL  7 DAY)) = MONTH(@target), 1, 0) +
 IF( MONTH(DATE_SUB( @target, INTERVAL 14 DAY)) = MONTH(@target), 1, 0) +
 IF( MONTH(DATE_SUB( @target, INTERVAL 21 DAY)) = MONTH(@target), 1, 0) +
 IF( MONTH(DATE_SUB( @target, INTERVAL 28 DAY)) = MONTH(@target), 1, 0) ) AS nth_weekday_of_month;

It seems relatively quick, but you could always create a pre-populated table (a few years out, or created by crons, etc.) with this function. 这似乎相对较快,但是您始终可以使用此功能创建一个预先填充的表(几年后,或者由cron等创建)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM