这个 SQL 函数如何获取上个月的第一天?

Posted

技术标签:

【中文标题】这个 SQL 函数如何获取上个月的第一天?【英文标题】:How is this SQL function getting the first day of the previous month? 【发布时间】:2019-03-25 14:24:42 【问题描述】:

我有一个函数可以获取上个月的第一天,但​​我想了解“DATEDIFF(month, -1, getdate()) - 2”部分它对获取上个月的第一天有何贡献月。完整的功能以代码形式给出。

我知道 dateadd 和 datediff 函数的作用,但我不确定 dateadd 函数中的 -1(在 datediff 函数中)和 -2 在做什么。

SELECT @prev_month_first_date = DATEADD(month, DATEDIFF(month, -1, getdate()) - 2, 0)

【问题讨论】:

【参考方案1】:

这样重写:

DATEADD(month, DATEDIFF(month, '20100101', getdate()) - 1, '20100101')

可能会更清楚。

发生了一些狡猾和晦涩的事情。

这个

DATEDIFF(month, -1, getdate())

计算两个日期之间跨越的月份边界,第一个是

   cast(-1 as datetime) --1899-12-31 00:00:00.000

然后它从中减去 2 并添加那个月数

 cast(0 as datetime) --1900-01-01 00:00:00.000

【讨论】:

对不起,只是检查一下,'20100101' 来自哪里? 这是一个任意的锚定日期。我通常会选择一个足够远的日子,不用担心负数(尽管它们在这里可以正常工作),但足够接近,以至于使用秒的 datediff 不会溢出。【参考方案2】:

-1 表示距离“零日期”(1900-01-01)的天数:

SELECT CONVERT(datetime, -1);

-- 1899-12-31 0:00

这是一种获取开始日期以执行日期差异的神秘方法,例如:

SELECT DATEDIFF(month, -1, getdate());
-- or
SELECT DATEDIFF(month, '18991231', getdate());

-- Both yield:
1431

所以表达式变成:

SELECT DATEADD(month, (1431 - 2), 0);

即“将 1429 个月添加到零日期 (1900-01-01)”:

SELECT DATEADD(month, (1431 - 2), '19000101');

产量:

2019-02-01 0:00

再次重申,0-1 在这里只是代表两个球门柱日期,用于神秘和“聪明”的计算。

就我个人而言,我觉得这种聪明的魔法令人困惑且无益。上个月的开始也可以用下面的表达式来表示,实际上是英文中比较容易理解的字符(从今天(1月25日)减去两个月,移到那个月(1 月 31 日),然后添加一天(2 月 1 日):

SELECT DATEADD(DAY,1,EOMONTH(DATEADD(MONTH,-2,GETDATE())));

只是展示了给这只猫剥皮的多种方法。 Gordon 的DATEFROMPARTS 也同样有效,我其实受不了EOMONTH() 函数,但是这种形式只允许你指定GETDATE() 一次。

【讨论】:

感谢您的回复亚伦。只需检查一下,简单来说,您将返回两个月,然后添加一天,这将导致上个月的第一天。只是想让你确认我的理解吗? @Ali_M 是的,没错,回到两个月前的最后一天,那么第二天就是一个月前的第一天。【参考方案3】:

我建议你使用这样的东西:

select dateadd(month, -1, datefromparts(year(getdate(), month(getdate(), 1))

这样做的意图要清楚得多。

【讨论】:

不幸的是,这并没有回答 OP 的问题。

以上是关于这个 SQL 函数如何获取上个月的第一天?的主要内容,如果未能解决你的问题,请参考以下文章

如何在n个月内使用sql(无程序)获取每个月的第一天和最后一天

如何用sql获取上个月的第一天和上个月的最后一天

如何使用js获取某月的第一天和最后一天

js如何获取上个月第一天和最后一天

如何在sql中从给定的月份和年份获取月份的第一天和最后一天

如何使用 Carbon 获取上个月的第一天和最后一天 - Laravel