我想选择自上个月20th
以来的所有行。
我知道我可以使用SELECT NOW() - INTERVAL 1 MONTH
选择一个月前的日期,但我如何设置该月的特定日期?
今天是March 28th
,我想选择所有比February 20th
新的行。
即使我可以直接设置日期,如果查询的日期是31st
,这对二月也不起作用,而是应该选择当月的最后一天。
注意:第20个只是一个示例,该值是在代码的其他地方动态生成的。
一些例子:
Day: 20th each month
Now: March 28th | Query: February 20th
Now: May 28th | Query: April 20th
Day: 31st each month
Now: March 28th | Query: February 28th // we select last day instead of 31st
Now: May 28th | Query: April 30th // we select last day instead of 31st
完整的查询将类似于SELECT * FROM sales WHERE date > SET_DAY(20, NOW() - INTERVAL 1 MONTH)
。
那么,我可以用什么来代替SET_DAY
(也适用于较短的月份(?
一个非常常见的用例是计费周期,您希望从当前计费周期中选择所有数据。
好吧,我相信这解决了的问题
select now()
- interval 1 month
- interval(
day(now())
- least(
20,
day(last_day(now() - interval 1 month))
)
) day
假设您在客户端中有一个参数是目标日期,并且您想在sql中验证它(确保您在上个月内找到一天(,而不是在客户端中,我会这样做:
least(
date(date_format(current_date - interval 1 month, '%Y-%m-01')) + interval ? - 1 day,
date(date_format(current_date, '%Y-%m-01')) - interval 1 day
)
注意:current_date将是连接时区中的当前日期,由客户端控制;如果我知道一天要在哪个时区,我更喜欢明确,比如:
date(convert_tz(utc_timestamp(), '+00:00', 'America/Los_Angeles'))
而不仅仅是current_date(两个位置(。
我刚刚意识到我的问题并没有包括所有的案例。如果最后一个计费日期在本月内,则应计算本月的20日(而不是前一个(。
根据@ysth的回答,我添加了一个IF来选择本月的20号(如果我们通过了它(,否则是上个月的:
IF(DAY(current_date) >= 20,
date(date_format(current_date, '%Y-%m-01')) + interval 20 - 1 day,
least(
date(date_format(current_date - interval 1 month, '%Y-%m-01')) + interval 20 - 1 day,
date(date_format(current_date, '%Y-%m-01')) - interval 1 day
)
);