如何在 SQL 中选择一个月的第一天?
Posted
技术标签:
【中文标题】如何在 SQL 中选择一个月的第一天?【英文标题】:How can I select the first day of a month in SQL? 【发布时间】:2010-12-03 23:53:52 【问题描述】:我只需要选择给定 DateTime 变量的月份的第一天。
我知道使用这种代码很容易做到:
select CAST(CAST(YEAR(@mydate) AS VARCHAR(4))
+ '/' + CAST(MONTH(@mydate) AS VARCHAR(2)) + '/01' AS DATETIME)
但不幸的是,这不是很优雅,也不是很快。
有没有更好的方法来做到这一点?我正在使用 SQL Server 2008。
【问题讨论】:
【参考方案1】:SELECT DATEADD(month, DATEDIFF(month, 0, @mydate), 0) AS StartOfMonth
【讨论】:
There is a cardinality estimation bug to be aware of if using this approach 应该注意,Martin Smith 提到的错误“只能”影响性能,而不是正确性。 这是explanation on why and how this works。 如果有人想知道SELECT EOMONTH(@mydate) AS EndOfMonth
会给你这个月的最后一天。
我如何确定上面提到的基数估计错误是否会影响我?它在 2010 年被标记为已修复。这是否意味着只有 SQL Server 2012 和更新版本是安全的,或者是否有可能已经修补了 2008 年的服务器?【参考方案2】:
除了以上所有的答案,还有一种基于sql 2012
中引入的函数的方式
SELECT DATEFROMPARTS(YEAR(@mydate),MONTH(@mydate),1)
【讨论】:
【参考方案3】:从 SQL Server 2012 开始:
SELECT DATEADD(DAY,1,EOMONTH(@mydate,-1))
【讨论】:
这似乎只适用于 2012 年及以后。 msdn.microsoft.com/en-us/library/hh213020.aspx 它的优点是它只提到了一次源日期,如果它是从函数调用派生的,那么它会更整洁。【参考方案4】:将字符串(即“2009 年 5 月 1 日”)转换为日期时间当然更清晰,但我们发现不久前的代码会返回当月的第一天...
DECLARE @Date DATETIME
//...
SELECT DATEADD(mm, DATEDIFF(mm,0,@Date), 0)
【讨论】:
【参考方案5】:简单查询:
SELECT DATEADD(m, DATEDIFF(m, 0, GETDATE()), 0)
-- Instead of GetDate you can put any date.
【讨论】:
我刚试了一下,效果很好。谢谢【参考方案6】:它可能相当快。为什么不将其创建为 sql 函数。
CREATE FUNCTION [dbo].[GetFirstDayOfMonth] ( @InputDate DATETIME )
RETURNS DATETIME
BEGIN
RETURN CAST(CAST(YEAR(@InputDate) AS VARCHAR(4)) + '/' +
CAST(MONTH(@InputDate) AS VARCHAR(2)) + '/01' AS DATETIME)
END
GO
【讨论】:
【参考方案7】:SELECT @myDate - DAY(@myDate) + 1
【讨论】:
真正简单而优雅的解决方案,但请记住,如果在变量中指定,这也会返回日期的时间部分。 我无法让它工作。除了额外的右括号外,我还收到此错误:Operand type ***: date is incompatible with int
。我猜是因为你想在约会时使用-
运算符?
我不知道它在性能方面有多好,但它确实可以胜任。
@Sam,您遇到了冲突,因为简单的算术 (+, -) 适用于日期时间,而不适用于日期。【参考方案8】:
当月的第一天和最后一天:
select dateadd(mm, -1,dateadd(dd, +1, eomonth(getdate()))) as FirstDay,
eomonth(getdate()) as LastDay
【讨论】:
【参考方案9】:这可能是一个新功能,但您也可以使用旧功能:
select DATEFROMPARTS(year(@mydate),month(@mydate),'01')
如果变量中的日期例如是'2017-10-29'
它将返回日期为'2017-10-01'
https://docs.microsoft.com/en-us/sql/t-sql/functions/datefromparts-transact-sql?view=sql-server-ver15
【讨论】:
【参考方案10】:这也有效:
SELECT DATEADD(DAY,(DATEPART(DAY,@mydate)-1)*(-1),@mydate) AS FirstOfMonth
【讨论】:
【参考方案11】:请使用这个
对于服务器 2012
DATEFROMPARTS(year('2015-06-30'),month('2015-06-30'),1)
在 Server 2012 之前
select cast(cast(year('2015-06-30') as varchar(4))+'-'+ cast(month('2015-06-30') as varchar(2))+'-01' as smalldatetime)
【讨论】:
【参考方案12】:未来的谷歌人,在 mysql 上,试试这个:
select date_sub(ref_date, interval day(ref_date)-1 day) as day1;
【讨论】:
这是一个sql-server
问题,date_sub
和interval
是mysql
。
好的,点,我编辑了回复。我认为它仍然与线程相关。【参考方案13】:
DECLARE @startofmonth date
SET @startofmonth = DATEADD(dd,1,EOMONTH(Getdate(),-2))
-2 将获得上个月的第一天。即,getdate() 是 10/15/18。您的结果将是 2018 年 9 月 1 日。更改为 -1,您的结果将是 10/1/18。 0 将是下个月的开始,2018 年 11 月 1 日.. 等等。
或
DECLARE @startofmonth date
SET @startofmonth = DATEADD(dd,1,EOMONTH(@mydate,-1))
【讨论】:
【参考方案14】:----Last Day of Previous Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0))
LastDay_PreviousMonth
----Last Day of Current Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0))
LastDay_CurrentMonth
----Last Day of Next Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+2,0))
LastDay_NextMonth
【讨论】:
但是 OP 正在寻找该月的第一天。最后一天,您可以只使用 EOMONTH() - 自 2012 年以来一直如此。【参考方案15】:我使用 GETDATE() 作为日期,您可以将其替换为您需要的日期。 以下是它的工作原理:首先我们将日期格式化为 YYYYMMDD... 格式截断以仅保留最左边的 6 个字符以便仅保留 YYYYMM 部分,然后将“01”附加为月份 - 瞧!你有当月的第一天。
SELECT CAST(CONVERT(VARCHAR(6),GETDATE(),112) +'01' AS DATETIME) AS StartOfMonth
顺便说一句,这方面的表现很棒!
【讨论】:
【参考方案16】:如果您今天正在查看此内容,并且使用 SQL Server 2012 或更高版本,则您拥有 EOMONTH 功能,这使事情变得更容易:
SELECT DATEADD(day, 1, EOMONTH(DATEADD(month, -1, GETDATE()))) as firstdateofmonth
你可以用你想要的任何日期变量来改变 GETDATE()。
【讨论】:
【参考方案17】:这里我们可以使用下面的查询来查询当月的第一个日期和这个月的最后一个日期。
SELECT DATEADD(DAY,1,EOMONTH(Getdate(),-1)) as 'FD',Cast(Getdate()-1 as Date)
as 'LD'
【讨论】:
【参考方案18】:如果使用 SQL Server 2012 或更高版本;
SELECT DATEADD(MONTH, -1, DATEADD(DAY, 1, EOMONTH(GETDATE())))
【讨论】:
【参考方案19】:尝试执行以下查询:
SELECT DATE_ADD(DATE_ADD(LAST_DAY(CURRENT_DATE-INTERVAL 1 DAY),INTERVAL 1 DAY),INTERVAL -1 MONTH)
【讨论】:
【参考方案20】:这个查询应该在 MySQL 上运行良好:
SELECT concat(left(curdate(),7),'-01')
【讨论】:
【参考方案21】:如果您想使用 sql server 2012+,可以尝试我使用的解决方案:
SELECT DATEADD(DAY, 1, EOMONTH(DATEADD(MONTH, -1, GETDATE())))
【讨论】:
【参考方案22】:选择 CONVERT(date,DATEADD(dd,-(DATEPART(dd,getdate())-1),getdate()),120)
此功能将为您提供月份开始日期的日期部分
【讨论】:
【参考方案23】:SELECT DATEADD (DAY, -1 * (DAY(GETDATE()) - 1), GETDATE())
.................................................. ......................
如果您不想要时间,则将其转换为 DATE,或者如果要将时间设置为 0:00:00,则转换为 DATE,然后再返回 DATETIME。
SELECT CONVERT (DATETIME,
CONVERT (DATE, DATEADD (DAY, -1 * (DAY(GETDATE()) - 1),
GETDATE())))
将 GETDATE() 更改为您想要的日期
【讨论】:
【参考方案24】:我个人推荐使用下面的sql,因为当我尝试在条件子句中使用日期函数时,它会大大降低我的查询速度。
无论如何都可以试试这个。
select CONCAT(DATEPART(YYYY,@mydate),'-',DATEPART(MM,@mydate),'-01')
【讨论】:
【参考方案25】:这里不与任何伟大的思想家竞争,而是一个与上面接受的答案略有不同的简单建议。
select dateadd(day, -(datepart(day,@date)+1,@date)
【讨论】:
【参考方案26】:我喜欢用FORMAT
,你甚至可以指定时间
SELECT FORMAT(@myDate,'yyyy-MM-01 06:00') first_of_a_month
【讨论】:
【参考方案27】:在 Sql Server 2012 中,
select getdate()-DATEPART(day, getdate())+1
select DATEADD(Month,1,getdate())-DATEPART(day, getdate())
【讨论】:
【参考方案28】:对于仍在寻找答案的任何人,这就像一种魅力,并且消除了任何日期添加。时间戳是可选的,以防需要指定,但也可以不指定。
SELECT left(convert(varchar, getdate(),23),7)+'-01 00:00:00'
【讨论】:
【参考方案29】:获取我们在 SQL 中作为参数传递的 Date 中的 First Date 和 Last Date
@date DATETIME
SELECT @date = GETDATE()
SELECT CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(@date)-1),@date),105) AS value,
'First Day of Current Month' AS name
UNION
SELECT CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(DATEADD(mm,1,@date))),
DATEADD(mm,1,@date)),105),
'Last Day of Current Month'
GO
**OutPut**
12/01/2019 First Day of Current Month
12/31/2019 Last Day of Current Month
【讨论】:
【参考方案30】:来点不一样的吧!使用格式。
DECLARE @Date Date =GetDate();
SELECT CONVERT(Date,Format(@Date,'yyyyMM01'));
如果我们要转换为日期列或变量,我们可以删除转换
DECLARE @Date Date =GetDate();
SELECT @Date =Format(@Date,'yyyyMM01');
SELECT [Date]=@Date
玩得开心:)
【讨论】:
以上是关于如何在 SQL 中选择一个月的第一天?的主要内容,如果未能解决你的问题,请参考以下文章