我正在尝试计算“当前周NOW()”的最后几年开始日和该周的结束日。除此之外,我需要一个补偿,因为有时一周的开始日可能不是星期日或星期一,但甚至可能是星期四。
如果一周从星期二开始,它将在星期一结束。鉴于此,如果当天是星期四,我需要能够计算星期二和星期一。
我知道如何获得去年的当天。
SELECT DATE_SUB(NOW(), INTERVAL 1 YEAR);
但是根据抵消要求,我在计算该周的开始日和该周的结束日期时遇到了问题。哪个需要采用“日期格式”。
* 努力澄清这一点......我的例子已经关闭......
***修改
为了争论(和例子),让我们说今天是2012年1月23日。我的任务是接受该日期并返回上一年那一周的开始和结束日期。
我的假设是:
1) a week is defined as having a thursday (ie 2011 week 1 is 1/2 - 1/8)
2) start of week is Sunday
根据我用上述假设所理解的周编号方案,第1周是星期四的第一周。这意味着,1月23日在2012年的第4周内。这已通过WEEK('2012-01-04') = 4
确认。因此,我的目标是选择上一年第4周的开始和结束日期。 2011年,结果将是1月23日至1月29日。
然后进一步复杂化是调整一周的开始(修改假设2)。继续使用WK4 ... 2011年1月23日 - 1月29日,周日 - 周六,如果我说本周开始是周一,那么我会将日期调整为1 ...给1月24日 - 1月30日。周二调整2月1日 - 1月25日 - 1月31日等。
方法分为两步: 1)计算 true 年周的开始和结束 2)无论开始日是什么,都将它滑入“未来”
虽然滑入未来可能会或可能不正确,但根据对“第4周”的含义的传统理解,它至少会产生一致的结果。
不幸的是,PHP不一定是一个选项。我们需要在SELECT START_WEEK,END_WEEK中运行它;
任何有关解决此查询的建议或帮助都会有所帮助。
由于
答案 0 :(得分:1)
好吧,ISO 8601假设:
1月23日属于2012年第4周,您可以通过
确认SELECT WEEK('2012-01-23', 3) = 4;
2012年第4周是1月23日至1月29日,您可以通过whatweekisit.com的日历确认。作为查询,您可以使用以下方式计算:
SELECT
WEEK('2012-01-23', 3) AS weekNumber,
DATE_SUB('2012-01-23', INTERVAL DAYOFWEEK('2012-01-23') - 2 DAY) AS startOfWeek,
DATE_ADD('2012-01-23', INTERVAL 8 - DAYOFWEEK('2012-01-23') DAY) as endOfWeek;
2011年第4周是1月24日至1月30日(也可通过日历确认)。确实,同一日期可能不在当前周数和去年的一周内,但我不怀疑它们会有很大不同。
SELECT
IF (WEEK('2012-01-23', 3) = WEEK(DATE_SUB('2012-01-23', INTERVAL 1 YEAR), 3),
DATE_SUB(DATE_SUB('2012-01-23', INTERVAL 1 YEAR), INTERVAL DAYOFWEEK(DATE_SUB('2012-01-23', INTERVAL 1 YEAR)) - 2 DAY),
DATE_SUB(DATE_SUB(DATE_ADD('2012-01-23', INTERVAL 6 DAY), INTERVAL 1 YEAR), INTERVAL DAYOFWEEK(DATE_SUB(DATE_ADD('2012-01-23', INTERVAL 6 DAY), INTERVAL 1 YEAR)) - 2 DAY)) AS datetimeStart;
请注意,我总是在几个地方逐字表示计算(例如2011年1月32日的DATE_SUB('2012-01-23', INTERVAL 1 YEAR)
);如果您在存储过程或UDF中执行此操作,则可以使用变量使其更简洁/可读/可维护。
现在已经确定了目标年份周的开始和结束,您可以简单地应用您的偏移量。鉴于$weekDayStart
为0 - 6(周日 - 周六):
SELECT
DATE_ADD(
IF (WEEK('2012-01-23', 3) = WEEK(DATE_SUB('2012-01-23', INTERVAL 1 YEAR), 3),
DATE_SUB(DATE_SUB('2012-01-23', INTERVAL 1 YEAR), INTERVAL DAYOFWEEK(DATE_SUB('2012-01-23', INTERVAL 1 YEAR)) - 2 DAY),
DATE_SUB(DATE_SUB(DATE_ADD('2012-01-23', INTERVAL 6 DAY), INTERVAL 1 YEAR), INTERVAL DAYOFWEEK(DATE_SUB(DATE_ADD('2012-01-23', INTERVAL 6 DAY), INTERVAL 1 YEAR)) - 2 DAY)),
INTERVAL $weekDayStart - 1 DAY) AS datetimeStart,
DATE_ADD(
IF (WEEK('2012-01-23', 3) = WEEK(DATE_SUB('2012-01-23', INTERVAL 1 YEAR), 3),
DATE_SUB(DATE_SUB('2012-01-23', INTERVAL 1 YEAR), INTERVAL DAYOFWEEK(DATE_SUB('2012-01-23', INTERVAL 1 YEAR)) - 2 DAY),
DATE_SUB(DATE_SUB(DATE_ADD('2012-01-23', INTERVAL 6 DAY), INTERVAL 1 YEAR), INTERVAL DAYOFWEEK(DATE_SUB(DATE_ADD('2012-01-23', INTERVAL 6 DAY), INTERVAL 1 YEAR)) - 2 DAY)),
INTERVAL $weekDayStart + 5 DAY) AS datetimeEnd;
因此,通过2012-01-23的输入和周四的开始日来完成它将产生:
答案 1 :(得分:0)
找到它......不得不再多阅读一下这个问题。 这最终成了7个不同的查询。
我的基本查询:
Sunday Start Day of Week
SELECT
DATE_SUB(
DATE_ADD(
STR_TO_DATE( CONCAT( YEAR('2012-01-04')-1, '-01-01' ), '%Y-%m-%d'), #Get last year starting date.
INTERVAL WEEK('2012-01-04') WEEK),
INTERVAL 6 DAY) START_DAY_OF_WEEK,
DATE_ADD(
STR_TO_DATE( CONCAT( YEAR('2012-01-04')-1, '-01-01' ), '%Y-%m-%d'),
INTERVAL WEEK('2012-01-04') WEEK) END_DAY_OF_WEEK;
这让我在2011年第1周开始。那个星期的开始是1/2,结束于1/8。 现在,如果我的星期在不同的一天开始,我会添加一个偏移...
Tuesday Start Day of Week
SELECT
DATE_SUB(
DATE_ADD(
STR_TO_DATE( CONCAT( YEAR('2012-01-04')-1, '-01-01' ), '%Y-%m-%d'), #Get last year starting date.
INTERVAL WEEK('2012-01-04') WEEK),
INTERVAL 4 DAY) START_DAY_OF_WEEK,
DATE_ADD(
DATE_ADD(
STR_TO_DATE( CONCAT( YEAR('2012-01-04')-1, '-01-01' ), '%Y-%m-%d'), #Get last year starting date.
INTERVAL WEEK('2012-01-04') WEEK),
INTERVAL 2 DAY) END_DAY_OF_WEEK;
这将给我1/4周的开始日,并以1/10结束。
要获得一周中的其他日子相对简单:
这是7个单独的查询,但确实使我能够做我想做的事。