MySQL里获取当前周、月、季的第一天/最后一天

这篇博客介绍了如何使用MySQL的内置函数来获取当前及前几周、月、季度的第一天和最后一天。示例查询展示了如何利用DATE_SUB、LAST_DAY、WEEKDAY和INTERVAL等函数来实现这些日期计算,对于数据库管理和数据分析非常有用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

mysql 获取当年第一天的年月日格式:

SELECT DATE_SUB(CURDATE(),INTERVAL dayofyear(now())-1 DAY);

MySQL里获取当前周、月、季的第一天/最后一天

当前一周的第一天:

select date_sub(curdate(),INTERVAL WEEKDAY(curdate()) + 1 DAY)

当前一周的最后一天:

select date_sub(curdate(),INTERVAL WEEKDAY(curdate())5 DAY)

前一周的第一天:

select date_sub(curdate(),INTERVAL WEEKDAY(curdate()) + 8 DAY)

前一周的最后一天:

select date_sub(curdate(),INTERVAL WEEKDAY(curdate()) + 2 DAY)

前两周的第一天:

select date_sub(curdate(),INTERVAL WEEKDAY(curdate()) + 15 DAY)

前两周的最后一天:

select date_sub(curdate(),INTERVAL WEEKDAY(curdate()) + 9 DAY)

当前月的第一天:

SELECT concat(date_format(LAST_DAY(now()),’%Y-%m-’),’01′)

当前月的最后一天:

SELECT LAST_DAY(now())

前一月的第一天:

SELECT concat(date_format(LAST_DAY(now() – interval 1 month),’%Y-%m-’),’01′)

前一月的最后一天:

SELECT LAST_DAY(now() – interval 1 month)

前两月的第一天:

SELECT concat(date_format(LAST_DAY(now() – interval 2 month),’%Y-%m-’),’01′)

前两月的最后一天:

SELECT LAST_DAY(now() – interval 2 month)

当前一季的第一天:

select concat(date_format(LAST_DAY(MAKEDATE(EXTRACT(YEAR FROM CURDATE()),1) + interval QUARTER(CURDATE())*3-3 month),’%Y-%m-’),’01′)

当前一季的最后一天:

select LAST_DAY(MAKEDATE(EXTRACT(YEAR FROM CURDATE()),1) + interval QUARTER(CURDATE())*3-1 month)

前一季的第一天:

select concat(date_format(LAST_DAY(MAKEDATE(EXTRACT(YEAR FROM CURDATE()),1) + interval QUARTER(CURDATE())*3-6 month),’%Y-%m-’),’01′)

前一季的最后一天:

select LAST_DAY(MAKEDATE(EXTRACT(YEAR FROM CURDATE()),1) + interval QUARTER(CURDATE())*3-4 month)

前两季的第一天:

select concat(date_format(LAST_DAY(MAKEDATE(EXTRACT(YEAR FROM CURDATE()),1) + interval QUARTER(CURDATE())*3-9 month),’%Y-%m-’),’01′)

前两季的最后一天:

select LAST_DAY(MAKEDATE(EXTRACT(YEAR FROM CURDATE()),1) + interval QUARTER(CURDATE())*3-7 month)
<think>我们想要获取当前日期所在度的最后一天。在MySQL中,没有直接给出度的最后一天的内置函数,但是我们可以通过计算得到。 一个度有3个,每个度的最后一天分别是: 第一度(1-3):331日 第二度(4-6):630日 第三度(7-9):930日 第四度(10-12):1231日 我们可以根据当前日期所在的度,计算出该度的最后一天。 步骤: 1. 获取当前日期的年份和度。 MySQL中可以使用QUARTER()函数获取当前日期所在的度(返回1-4)。 2. 根据度推算出该度的最后一个(3、6、9、12)的最后一天。 注意:每个度的最后一天就是该最后一个(即3、6、9、12)的最后一天。 3. 使用LAST_DAY()函数可以获取给定份的最后一天。 但是,如何构造一个该最后一个的日期呢?我们可以: - 第一度:年份 + '-03-01' - 第二度:年份 + '-06-01' - 第三度:年份 + '-09-01' - 第四度:年份 + '-12-01' 然后使用LAST_DAY()函数。 因此,我们可以这样写: CASE WHEN QUARTER(CURRENT_DATE) = 1 THEN LAST_DAY(CONCAT(YEAR(CURRENT_DATE), '-03-01')) WHEN QUARTER(CURRENT_DATE) = 2 THEN LAST_DAY(CONCAT(YEAR(CURRENT_DATE), '-06-01')) WHEN QUARTER(CURRENT_DATE) = 3 THEN LAST_DAY(CONCAT(YEAR(CURRENT_DATE), '-09-01')) WHEN QUARTER(CURRENT_DATE) = 4 THEN LAST_DAY(CONCAT(YEAR(CURRENT_DATE), '-12-01')) END 但是,我们可以更简洁地写,因为每个度的最后一个是3*度(即3,6,9,12),所以我们可以用公式: 份 = QUARTER(当前日期) * 3 然后构造这个第一天,再取最后一天。 但是注意:12是第四度,4*3=12,没问题。但第一度是1,1*3=3,第二度是2*3=6,第三度是3*3=9,都符合。 因此,我们可以这样构造日期字符串: 年份 + '-' + (度*3) + '-01' 但是,注意份是两位数,所以当月份是一位数时,需要格式化为两位。我们可以使用LPAD函数,但也可以直接使用数字,因为MySQL的日期函数可以接受一位数的份。 然而,为了确保正确,我们可以使用DATE_FORMAT来构造,但这我们直接使用整数拼接,然后转换成日期。 所以,查询可以写成: SELECT LAST_DAY(CONCAT(YEAR(CURRENT_DATE), '-', QUARTER(CURRENT_DATE)*3, '-01')); 但是,这样会有一个问题:当月份是3,6,9,12时,拼接出来的字符串是有效的,但是注意,比如3会拼接成'2024-3-01',这也是合法的,MySQL可以识别。 但是,为了确保万无一失,我们可以使用STR_TO_DATE或者DATE函数,但这我们直接使用字符串拼接然后LAST_DAY。 但是,注意:如果当前日期是无效的,那么LAST_DAY会返回NULL,但这我们使用当前日期,所以不会无效。 但是,我们也可以使用MAKEDATE函数,但这用字符串拼接更简单。 因此,完整的查询语句为: ```sql SELECT LAST_DAY(CONCAT(YEAR(CURDATE()), '-', LPAD(QUARTER(CURDATE())*3, 2, '00'), '-01')) AS last_day_of_quarter; ``` 或者,不使用LPAD,因为即使是一位数,MySQL也能识别,但为了规范,我们可以使用LPAD确保份是两位数。 但是,测试发现,当月份为10,11,12时,我们这不会出现,因为度*3得到的是3,6,9,12,都是两位数只有3,6,9是一位数,所以我们可以用LPAD(数字,2,'0'),这样3变成'03',6变成'06',9变成'09',12变成'12'。 所以改进为: ```sql SELECT LAST_DAY(CONCAT(YEAR(CURDATE()), '-', LPAD(QUARTER(CURDATE())*3, 2, '0'), '-01')) AS last_day_of_quarter; ``` 但是,注意:LPAD的第三个参数是填充字符,我们写'0',并且指定长度为2,这样就会在左边补0到两位。 另外,我们也可以使用DATE_FORMAT来构造,但这用CONCAT和LPAD已经足够。 另一种方法是使用DATE_ADD和MAKEDATE,但比较复杂。 我们还可以这样:先得到当前度的第一天,然后加上3个再减去1天?不对,因为一个度是3个,所以当前度的第一天加上3个就是下一个度的第一天,再减去1天就是当前度的最后一天。 步骤: 1. 计算当前度的第一天: DATE_FORMAT(当前日期, '%Y-%m-01') 不行,因为不是每度的第一天是11日、41日等。 如何得到当前度的第一天度q = QUARTER(当前日期) 那么: q=1 -> 11日 q=2 -> 41日 q=3 -> 71日 q=4 -> 101日 所以,当前度的第一天 = CONCAT(YEAR(当前日期), '-', (QUARTER(当前日期)*3-2), '-01') 然后,当前度的最后一天 = 当前度的第一天 + 间隔3个 - 1天 但是,注意:加3个是下个度的第一天,减1天就是本度的最后一天。 所以,可以这样写: SELECT DATE_SUB(DATE_ADD(MAKEDATE(YEAR(CURDATE()), 1) + INTERVAL (QUARTER(CURDATE())*3-3) MONTH, INTERVAL 3 MONTH), INTERVAL 1 DAY); 这种方法比较复杂,而且容易出错。 因此,我们采用第一种方法:直接构造该最后一个(即3,6,9,12)的第一天,然后取这个最后一天。 所以,我们选择第一种方法。 但是,我们也可以使用第二种方法(利用度的第一天加3个减1天)来验证第一种方法。 第二种方法实现: 第一步:构造当前度的第一天(字符串): CONCAT(YEAR(CURDATE()), '-', LPAD((QUARTER(CURDATE())-1)*3+1, 2, '0'), '-01') 第二步:将这个日期加上3个,得到下个度的第一天,然后减去1天。 所以: SELECT DATE_SUB(DATE_ADD(STR_TO_DATE(CONCAT(YEAR(CURDATE()), '-', LPAD((QUARTER(CURDATE())-1)*3+1, 2, '0'), '-01'), '%Y-%m-%d'), INTERVAL 3 MONTH), INTERVAL 1 DAY); 这个表达式比较长。 因此,我们推荐第一种方法。 现在,我们写第一种方法的查询: ```sql SELECT LAST_DAY( CONCAT( YEAR(CURDATE()), '-', LPAD(QUARTER(CURDATE()) * 3, 2, '0'), '-01' ) ) AS last_day_of_quarter; ``` 测试:假设当前日期是'2023-11-21',那么度是4(第四度),份=4*3=12,构造日期'2023-12-01',然后LAST_DAY('2023-12-01')得到'2023-12-31'。 但是,注意:如果当前日期是2024年2(第一度),度=1,份=3,构造'2024-03-01',最后一天是2024-03-31。 所以,这个方法是可行的。 另外,我们也可以使用CURDATE()来获取当前日期,或者使用NOW(),但NOW()包含时间,不过我们这只需要日期部分,所以用CURDATE()即可。 因此,最终查询语句为:</think>### MySQL 获取当前最后一天的解决方案 在 MySQL 中,可以通过以下步骤获取当前日期所在度的最后一天: #### 核心方法 ```sql SELECT LAST_DAY( MAKEDATE(YEAR(CURDATE()), 1) + INTERVAL (QUARTER(CURDATE()) * 3 - 1) MONTH ) AS quarter_end; ``` #### 原理解析 1. **`CURDATE()`** 获取当前日期(如:2023-11-21) 2. **`YEAR(CURDATE())`** 提取当前年份(如:2023) 3. **`QUARTER(CURDATE())`** 获取当前度(1-4),例如: - 1-3 → 1 - 4-6 → 2 - 7-9 → 3 - 10-12 → 4 4. **最后份计算** `QUARTER() * 3` 得到最后份(3/6/9/12),`-1` 调整为份偏移量 5. **`MAKEDATE()` + `INTERVAL`** 构造最后份的第一天: ```math \text{MAKEDATE}(2023,1) + \text{INTERVAL } (4\times3-1) \text{ MONTH} = 2023-12-01 ``` 6. **`LAST_DAY()`** 获取份的最后一天(如:2023-12-31)[^1] #### 完整示例 ```sql -- 创建测试表 CREATE TABLE sales ( id INT PRIMARY KEY, sale_date DATE ); -- 插入测试数据 INSERT INTO sales VALUES (1, '2023-02-15'), -- Q1 (2, '2023-05-20'), -- Q2 (3, '2023-08-10'), -- Q3 (4, '2023-11-21'); -- Q4 -- 查询每笔销售数据所在度的最后一天 SELECT id, sale_date, LAST_DAY( MAKEDATE(YEAR(sale_date), 1) + INTERVAL (QUARTER(sale_date) * 3 - 1) MONTH ) AS quarter_end FROM sales; ``` #### 查询结果 | id | sale_date | quarter_end | |----|-------------|-------------| | 1 | 2023-02-15 | 2023-03-31 | | 2 | 2023-05-20 | 2023-06-30 | | 3 | 2023-08-10 | 2023-09-30 | | 4 | 2023-11-21 | 2023-12-31 | #### 特殊日期处理 ```sql -- 处理闰年(2024是闰年) SELECT LAST_DAY('2024-02-01'); -- 返回 2024-02-29 [^1] -- 无效日期返回 NULL SELECT LAST_DAY('2023-02-30'); -- 返回 NULL [^1] ``` #### 使用场景 1. **财务度报表** ```sql SELECT quarter_end, SUM(amount) AS total_sales FROM transactions WHERE transaction_date <= quarter_end GROUP BY quarter_end; ``` 2. **合同到期提醒** ```sql SELECT contract_id, end_date FROM contracts WHERE end_date = ( SELECT LAST_DAY(MAKEDATE(YEAR(CURDATE()),1) + INTERVAL (QUARTER(CURDATE())*3-1) MONTH) ); ``` --- ### 相关问题 1. 如何计算任意日期所在度的第一天? 2. 在 WHERE 条件中如何使用最后一天进行过滤? 3. 如何优化包含 `LAST_DAY()` 函数的大数据量查询?[^4] 4. 不同数据库(如 PostgreSQL/Oracle)的度计算函数有何差异? 5. 如何处理跨年度的度计算(如 2023-Q4 与 2024-Q1)?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值