如何在SQL中选择一个月的第一天?


308

我只需要选择给定datetime变量的月份的第一天。

我知道使用这种代码非常容易:

select CAST(CAST(YEAR(@mydate) AS VARCHAR(4)) 
+ '/' + CAST(MONTH(@mydate) AS VARCHAR(2)) + '/01' AS DATETIME)

但这不是很优雅,也可能不是很快。

有一个更好的方法吗?我正在使用SQL Server 2008。

Answers:


603
SELECT DATEADD(month, DATEDIFF(month, 0, @mydate), 0) AS StartOfMonth


63
应当指出,马丁·史密斯(Martin Smith)提到的错误只能“影响”性能,而不能影响正确性。
Olson.dev 2014年


34
如果有人想知道SELECT EOMONTH(@mydate) AS EndOfMonth会给您该月的最后一天。
哈里日

3
我如何确定所指出的基数估计错误是否会影响我?它在2010年标记为已修复。这是否意味着只有SQL Server 2012和更高版本才是安全的,或者是否可能已对2008服务器进行了修补?
乔恩

134

除了以上所有答案外,一种基于 sql 2012

SELECT DATEFROMPARTS(YEAR(@mydate),MONTH(@mydate),1)


14

将字符串(即“ 2009年5月1日”)强制转换为日期时间肯定更清晰,但我们发现前段代码可以返回该月的第一天。

DECLARE @Date DATETIME
//...
SELECT DATEADD(mm, DATEDIFF(mm,0,@Date), 0)


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


3

请用这个

  1. 对于Server 2012

    DATEFROMPARTS(year('2015-06-30'),month('2015-06-30'),1)
  2. 在Server 2012之前

    select  cast(cast(year('2015-06-30') as varchar(4))+'-'+ cast(month('2015-06-30') as varchar(2))+'-01' as smalldatetime)

3

本月的第一天和最后一天:

select dateadd(mm, -1,dateadd(dd, +1, eomonth(getdate()))) as FirstDay, 
eomonth(getdate()) as LastDay

2
SELECT @myDate - DAY(@myDate) + 1

真正简单而优雅的解决方案,但请记住,如果在变量中指定了日期,则它还会返回日期的时间部分。
kuklei 2014年

我无法使它正常工作。除了多余的右括号外,我还会收到此错误:Operand type clash: date is incompatible with int。我猜是因为您要-在日期上使用运算符?
山姆

我不知道它在性能方面有多好,但是确实可以做到。
salcoin 2015年

@Sam,您会发生冲突,因为简单的算术(+,-)在日期时间有效,而不是日期有效。
darlove

2
----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
。– deutschZuid


1

未来的Googlers,在MySQL上,请尝试以下操作:

select date_sub(ref_date, interval day(ref_date)-1 day) as day1;

3
这是一个sql-server问题,date_sub并且intervalmysql
OGHaza

很好,我编辑了回复。我认为它仍然与线程相关。
Ariel T

1

我使用GETDATE()作为要使用的日期,您可以将其替换为所需的日期。
这是这样工作的:首先,我们将日期格式设置为YYYYMMDD ...格式,将其截断以仅保留最左边的6个字符,以便仅保留YYYYMM部分,然后将“ 01”添加为月份-瞧!您拥有当月的第一天。

SELECT CAST(CONVERT(VARCHAR(6),GETDATE(),112) +'01' AS DATETIME) AS StartOfMonth

顺便说一句,这是很棒的表现!


1

如果您今天正在使用SQL Server 2012或更高版本进行查看,则可以使用EOMONTH函数,该函数使事情变得简单:

SELECT DATEADD(day, 1, EOMONTH(DATEADD(month, -1, GETDATE()))) as firstdateofmonth

您可以使用所需的任何日期变量更改GETDATE()。


1

在这里,我们可以使用下面的查询来查询月份的第一个日期和月份的最后一个日期。

SELECT DATEADD(DAY,1,EOMONTH(Getdate(),-1)) as 'FD',Cast(Getdate()-1 as Date)
as 'LD'

1

如果使用SQL Server 2012或更高版本;

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

1
DECLARE @startofmonth date
SET @startofmonth = DATEADD(dd,1,EOMONTH(Getdate(),-2))

-2将带您上个月的第一天。即,getdate()是10/15/18。您的结果将是9/1/18。更改为-1,您的结果将是10/1/18。0将是下个月的开始,2018年11月1日。等等。

要么

DECLARE @startofmonth date
SET @startofmonth = DATEADD(dd,1,EOMONTH(@mydate,-1))

1

尝试执行以下查询:

SELECT DATE_ADD(DATE_ADD(LAST_DAY(CURRENT_DATE-INTERVAL 1 DAY),INTERVAL 1 DAY),INTERVAL -1 MONTH)


0

选择CONVERT(date,DATEADD(dd,-(DATEPART(dd,getdate())-1),getdate()),120)

此功能将为您提供月份开始日期的日期部分


0
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()更改为所需的日期


0

我个人建议使用下面的sql,因为当我尝试在condition子句中使用date函数时,它会大大降低我的查询速度。

无论如何都可以尝试一下。

select CONCAT(DATEPART(YYYY,@mydate),'-',DATEPART(MM,@mydate),'-01')

0

不是要与这里的任何优秀人士竞争,而是一个简单的建议,与上面接受的答案有些不同。

select dateadd(day, -(datepart(day,@date)+1,@date)

0

我喜欢使用FORMAT,甚至可以指定时间

SELECT FORMAT(@myDate,'yyyy-MM-01 06:00') first_of_a_month

0

在Sql Server 2012中,

 select getdate()-DATEPART(day, getdate())+1

 select DATEADD(Month,1,getdate())-DATEPART(day, getdate())

0

该查询在MySQL上应该可以很好地工作:

SELECT concat(left(curdate(),7),'-01') 

0

对于仍在寻找答案的任何人,这就像一个咒语,并且消除了任何添加的日期。如果需要指定时间戳,则时间戳是可选的,但也可以不使用。

SELECT left(convert(varchar, getdate(),23),7)+'-01 00:00:00'

0

在SQL中作为参数传递的日期中获取第一个日期和最后一个日期

     @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

-3

这是您在MySQL中的处理方式:

  select DATE_FORMAT(NOW(), '%Y-%m-1')

4
请指定这不是sql-server答案,但仅适用于MySQL。
kuklei 2014年

对于SQL Server,您可以使用SELECT FORMAT(GETDATE(), 'yyyy-MM-01')
NASSER

不要鼓励人们将日期格式设置为字符串,只是为了做一些可以并且应该以数字方式完成的事情。这就像在说:“您可以将数字格式化为字符串,将除最后两位之外的所有数字都进行子字符串化,然后将其连接为'00',从而将数字四舍五入到最接近的100”
Caius Jard
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.