给出一个表orders
:
+-----+---------+-------------------------+
| id | price | created_at |
+-----+---------+-------------------------+
| 1 | 16.50 | 2017-02-28 12:52:00.824 |
| 2 | 22.00 | 2017-10-03 15:12:39.107 |
| 3 | 50.00 | 2017-12-03 12:54:42.658 |
| 4 | 12.00 | 2018-01-02 07:21:47.808 |
| . | . | . |
| . | . | . |
| . | . | . |
+-----+---------+-------------------------+
和当前日期:
+---------------------+
| NOW() |
+---------------------+
| 2018-01-03 10:33:14 |
+---------------------+
我想选择几个月前当天创建的所有记录。因此,对于上述数据,我的查询应返回:
+-----+---------+-------------------------+
| id | price | created_at |
+-----+---------+-------------------------+
| 2 | 22.00 | 2017-10-03 15:12:39.107 |
| 3 | 50.00 | 2017-12-03 12:54:42.658 |
+-----+---------+-------------------------+
但是在一个月的最后一天有一些边缘情况:
我尝试的是这样的:
SELECT * FROM orders
JOIN (
SELECT id, PERIOD_DIFF(
DATE_FORMAT(NOW(), "%Y%m"),
DATE_FORMAT(created_at, "%Y%m")
) AS diff
FROM orders
) AS periods
ON orders.id = periods.id
WHERE DATEDIFF(created_at + INTERVAL diff MONTH, NOW()) = 0;
但它并没有覆盖边缘情况,我相信有一种更聪明的方式(可能没有子查询)来实现预期的结果。
<小时/> 修改 为了给你更多的背景 - 我需要的是一种循环。我有一个cron job
计划每天午夜运行一次。此作业应选择几个月前当天创建的ids
orders
,然后刷新与ids
相关的其他一些数据。重要的是每月刷新一次这个数据 - 这就是为什么几个月的最后一天如此重要。
例如,给定以下创建日期:
DATES = [
2015-05-30, 2016-02-29, 2016-10-03,
2016-12-31, 2017-05-28, 2018-01-03
]
+---------------+------------------------------------+
| NOW() | SHOULD BE INCLUDED |
+---------------+------------------------------------+
| 2018-01-03 | 2016-10-03, 2018-01-03 |
| 2018-02-28 | 2016-02-29, 2016-12-31, 2017-05-28 |
| 2018-04-30 | 2015-05-30, 2016-12-31 |
| 2018-10-31 | 2016-12-31 |
+---------------+------------------------------------+
答案 0 :(得分:1)
使用DAYOFMONTH()函数比较NOW()和created_at的日期。 像这样:
SELECT * FROM ORDERS
WHERE (DAYOFMONTH(NOW() < LAST_DAY(NOW()) -- if not last day of month
AND DAYOFMONTH(created_at) = DAYOFMONTH(NOW())
OR (LAST_DAY(NOW()) = DAYOFMONTH(NOW()) -- if last day of month
AND DAYOFMONTH(NOW()) BETWEEN DAYOFMONTH(created_at) AND LAST_DAY(created_at)) --
答案 1 :(得分:1)
我可以建议稍微简化Walerian吗?
SELECT
*
FROM
orders
WHERE
(
DAYOFMONTH(created_at) = DAYOFMONTH( NOW() ) --monthdays that match
)
OR
(
( DAYOFMONTH( LAST_DAY( NOW() ) ) = DAYOFMONTH( NOW() ) ) --base date is end of month
AND
( DAYOFMONTH(created_at) > DAYOFMONTH( NOW() ) ) --target monthdays are beyond base monthday
)
顺便说一下,我没有MySQL环境,所以我只是相信这些是MySQL中正确的功能。
答案 2 :(得分:0)
受到suresubs's回答的启发,我弄清楚查询应该是什么样子。
SELECT * FROM orders
-- (1)
WHERE (DAYOFMONTH(NOW) < DAYOFMONTH(LAST_DAY(NOW()))
AND DAYOFMONTH(created_at) = DAYOFMONTH(NOW()))
-- (2)
OR (DAYOFMONTH(LAST_DAY(NOW())) = DAYOFMONTH(NOW())
AND DAYOFMONTH(created_at) BETWEEN DAYOFMONTH(NOW()) AND DAYOFMONTH(LAST_DAY(created_at)));
它使用DAYOFMONTH()
和LAST_DAY()
函数,它分为两种情况: