SQL 日期函数如何获取上个月最后一天?

这事儿我得跟你唠唠。
前年我在上海做项目,遇到个坑,就是怎么搞上个月最后一天的日期。
试了好几种方法,最后还是用对的方法省心。

就说MySQL吧,我当年试过LAST_DAY函数,挺好使。
比如,我写个SELECT LAST_DAY(CURDATE()
INTERVAL 1 MONTH) AS last_day_prev_month; 这句,直接就给我上个月最后一天。
原理也简单,CURDATE()-INTERVAL 1 MONTH先找到上个月同一天,LAST_DAY再给你转成最后一天。

后来又试了DATE_SUB函数,也行。
SELECT LAST_DAY(DATE_SUB(CURDATE(), INTERVAL 1 MONTH)) AS last_day_prev_month; 这句也行。
就是感觉LAST_DAY更直接。

再说说SQL Server,那会儿在杭州,他们用EOMONTH函数。
SELECT EOMONTH(GETDATE(), -1 ) AS last_day_prev_month; 这句真方便,直接就给了上个月最后一天。
原理就是告诉它GETDATE()是现在日期,-1 是上个月,它自己就给你算出来了。

PostgreSQL那会儿没怎么碰,但看文档, DATE_TRUNC('month', CURRENT_DATE)
INTERVAL '1 day'::date 这句听着也行。
就是把当前日期按月截断,再减一天,就成了上个月最后一天。

要是数据库没自带函数,比如早期用的某种小数据库,就得自己搞。
我记得当年试过MySQL的,先找本月第一天,DATE_FORMAT(CURDATE()
INTERVAL DAY(CURDATE())
1 DAY, '%Y-%m-%d') AS first_day_current_month; 这句找本月第一天,再减一天,就成了上个月最后一天。
但要注意,这得调整,不同数据库可能不一样。

最要注意的是时区。
前年那会儿,我们项目时区搞错了,结果日期全乱套。
所以,确保数据库时区跟业务需求一致,特别重要。
还有边界情况,比如当前日期是1 号,直接减一个月,可能就变成上个月1 号了,得用LAST_DAY或EOMONTH确保是最后一天。

总之,MySQL用LAST_DAY,SQL Server用EOMONTH,PostgreSQL用DATE_TRUNC,其他数据库就自己捣鼓或者查文档。
这事儿真不难,但当年我踩坑也踩了不少,都是这些细节闹的。

SQL:从时间戳日期中减去一天。

结论:PostgreSQL减时间戳一天用INTERVAL。

方法:INTERVAL'1 day'。

注意:列类型为TIMESTAMP。

示例:SELECT date_at INTERVAL '1 day' FROM your_table;
小心:整数减法会导致错误。

你自己掂量。

SQL请教大家一个日期的加减法

我记得有一次,我在数据库里处理订单时间,需要计算订单到期的时间。
我用了 date_add 函数,当时加了一个月。
比如,订单是在2 02 3 年3 月1 5 日创建的,我想要计算一个月后,也就是4 月1 5 日的订单到期时间。
我写的是 select date_add('2 02 3 -03 -1 5 ', interval 1 month);,结果出来是 2 02 3 -04 -1 5 ,正好是预期的日期。

但是,我突然想到,如果我要计算订单到期的时间,还需要考虑时区问题。
比如,如果公司总部在纽约,而订单是在东京创建的,那么时区差异就需要考虑进去。
如果东京比纽约快9 个小时,那么我计算到期时间的时候,可能需要这样写 select date_add('2 02 3 -03 -1 5 ', interval 1 month) + interval 9 hour;。

不过,我又想到,如果公司有多个时区,每个时区都要手动计算,那岂不是太麻烦了?有没有什么办法可以自动转换时区呢?等等,还有个事,我之前看到一个函数叫 CONVERT_TZ,它是用来转换时区的,但是我不确定它是不是在所有数据库中都可用。
这事儿,我得查查资料。

SQL请教大家一个日期的加减法

哎,这SQL日期加减的操作,我当年刚接手一个老系统时,真是头疼了好一阵子。

记得那是前年,在一个银行的项目里,对吧?他们有个报表需求,要统计上个月的数据。
那会儿系统里的日期字段就只有一个 transaction_date,类型是 DATE。

我一开始想当然,想用 transaction_date
INTERVAL 1 MONTH,结果提示错误。
后来查了查,那个旧系统用的数据库是 SQL Server,不是 MySQL。
嚯,这语法就不通用了。

好在最后找到了 DATEADD 这个函数。
就是像你说的这么用: sql SELECT DATEADD(month, -1 , transaction_date) as last_month_date FROM transactions;
这样就能把日期往后推一个月了。
那个月,我改了小几十张类似的报表,全是这个逻辑。

后来又遇到个情况,是统计某个产品下线前一天的用户行为。
那天,数据量特别大,得有五六十万条记录。
用户问为啥跑得慢,我一查,发现原来我在 product_off_date 这个字段上直接用了 product_off_date
INTERVAL 1 DAY。

你猜怎么着?这次是 MySQL,结果还是不行。
得用 DATE_SUB: sql SELECT DATE_SUB(product_off_date, INTERVAL 1 DAY) as day_before_off FROM product_logs;
这下才对。
不过我后来发现,如果 product_off_date 刚好是月初或者月中,用 DATE_SUB 推前一天,结果有时候会变成上个月的最后一天。
比如 3 月1 号减一天,就变成2 月2 8 号了。
这得额外注意下。

总的来说,这事儿给我留下的印象就是:用 DATEADD 还是 DATE_SUB,得看你用的数据库系统是啥。
SQL Server用 DATEADD,MySQL用 DATE_SUB。
月份减一加一,天数也是同理,就是参数 month day 之类的得改。

哦对了,还有个情况,当年在一个电商项目里,遇到一个坑。
他们把生日存成了 yyyyMMdd 格式的数字,比如 '1 9 9 005 2 1 '。
想给用户发生日优惠券,得先把数字转成日期再减一天。
那真是硬着头皮,用 CONVERT(DATE, '1 9 9 005 2 1 ')
INTERVAL 1 DAY,结果发现性能特别差。
后来改用字符串函数拆分再转,才好点。

不过现在啊,新系统设计,日期一般都直接存 DATE 类型了,这日期加减的操作,也就这么回事。
你说的 DateAdd 语法,在 SQL Server 上是对的,月份减一、日期减一,就是这么用。

行了,不啰嗦了。
这事儿就是这样,踩过坑才知道。