Como posso selecionar o primeiro dia do mês no SQL?


308

Eu só preciso selecionar o primeiro dia do mês de uma determinada variável datetime.

Eu sei que é muito fácil fazer isso usando esse tipo de código:

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

Mas isso não é muito elegante e provavelmente também não é muito rápido.

Existe uma maneira melhor de fazer isso? Estou usando o SQL Server 2008.

Respostas:


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


63
Note-se que o bug mencionado por Martin Smith pode "apenas" afetar o desempenho, não a correção.
precisa saber é o seguinte


34
Caso alguém esteja se perguntando SELECT EOMONTH(@mydate) AS EndOfMonth, você terá o último dia do mês.
hallizh

3
Como posso determinar se o erro de estimativa de cardinalidade observado me afetará? Ele está marcado como corrigido em 2010. Isso significa que apenas o SQL Server 2012 e mais recentes são seguros, ou é possível que um servidor 2008 tenha sido corrigido?
Jon

134

Além de toda a resposta acima, uma maneira baseada em uma função introduzida no sql 2012

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


14

A conversão de uma string (ou seja, "5/1/2009") para data e hora é certamente mais legível, mas encontramos um código que retornaria no início do mês ...

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

10

Consulta simples:

SELECT DATEADD(m, DATEDIFF(m, 0, GETDATE()), 0) 
-- Instead of GetDate you can put any date.

6

Provavelmente é bastante rápido. Por que não criá-lo como uma função 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

4

Isso também funciona:

    SELECT DATEADD(DAY,(DATEPART(DAY,@mydate)-1)*(-1),@mydate) AS FirstOfMonth

3

Por favor use isso

  1. Para Server 2012

    DATEFROMPARTS(year('2015-06-30'),month('2015-06-30'),1)
  2. Antes do Server 2012

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

3

Primeiro e último dia do mês atual:

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

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

Solução realmente simples e elegante, mas lembre-se de que isso também retorna a parte da hora da data, se especificado na variável.
Kuklei 17/10

Não consegui fazer isso funcionar. Além do colchete de fechamento extra, eu recebo este erro: Operand type clash: date is incompatible with int. Eu acho que é porque você está tentando usar o -operador em um encontro?
Sam

Não sei como é bom em termos de desempenho, mas certamente faz o trabalho.
Salcoin

@ Sam, você tem um conflito porque a aritmética simples (+, -) funciona às vezes, e não às datas.
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

Mas o OP está procurando o primeiro dia do mês. No último dia, você pode usar EOMONTH () - está assim desde 2012. #
deutschZuid


1

Futuros googlers, no MySQL, tente o seguinte:

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

3
Esta é uma sql-serverpergunta, date_sube intervalé mysql.
OGHaza

Bom, ponto, editei a resposta. Eu acho que ainda é relevante para o segmento.
Ariel T

1

Eu usei GETDATE () como uma data para trabalhar, você pode substituí-lo pela data que você precisa.
Veja como isso funciona: Primeiro, formate a data no formato AAAAMMDD ... truncando para manter apenas os 6 caracteres mais à esquerda, para manter apenas a parte AAAAMM e, em seguida, acrescente '01' como o mês - e pronto! você tem o primeiro dia do mês atual.

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

BTW, o desempenho é ótimo nisso!


1

Se você está analisando isso hoje e usando o SQL Server 2012 ou mais recente, tem a função EOMONTH que facilita as coisas:

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

Você pode alterar GETDATE () com qualquer variável de data que desejar.


1

Aqui, podemos usar a consulta abaixo para a primeira data do mês e a última data do mês.

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

1

Se estiver usando o SQL Server 2012 ou superior;

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

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

O -2 o levará ao primeiro dia do mês passado. ou seja, getdate () é 15/10/18. Seus resultados seriam 1/9/18. Mude para -1 e seus resultados serão 1/10/18. 0 seria o início do próximo mês, 01/11/2018 .. etc etc.

ou

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

1

Tente executar a seguinte consulta:

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


0

selecione CONVERT (data, DATEADD (dd, - (DATEPART (dd, getdate ()) - 1), getdate ()), 120)

Esta função fornece a data parte da data de início do mês


0
SELECT DATEADD (DAY, -1 * (DAY(GETDATE()) - 1), GETDATE())

.................................................. ...................

Se você não quiser o horário, converta-o para DATE ou, se quiser fazer o horário para 0:00:00, converta para DATE e depois volte para DATETIME.

SELECT CONVERT (DATETIME,  
CONVERT (DATE, DATEADD (DAY, -1 * (DAY(GETDATE()) - 1),
GETDATE())))

Altere GETDATE () para a data desejada


0

Pessoalmente, recomendei que o sql abaixo, porque quando tento usar a função date na cláusula condition, diminui muito a velocidade da minha consulta.

de qualquer forma, sinta-se livre para tentar isso.

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

0

Não para competir com nenhuma das grandes mentes aqui, mas uma sugestão simples um pouco diferente da resposta aceita acima.

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

0

Eu gosto de usar FORMAT, você pode até especificar um horário

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

0

No Sql Server 2012,

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

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

0

Esta consulta deve funcionar muito bem no MySQL:

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

0

Para quem ainda procura uma resposta, isso funciona como um encanto e acaba com todos os dados. O registro de data e hora é opcional, caso seja necessário especificar, mas funciona sem ele também.

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

0

Obter primeira data e última data na data que passamos como parâmetro no 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

Aqui está como você faria isso no MySQL:

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

4
Por favor, especifique que esta não é a resposta do sql-server, mas funciona apenas no MySQL.
Kuklei 17/10

Para o SQL Server, você pode usarSELECT FORMAT(GETDATE(), 'yyyy-MM-01')
NASSER

Não incentive as pessoas a formatar datas em strings apenas para fazer algo que pode e deve ser feito numericamente. É como dizer "você pode arredondar um número até os 100 mais próximos, formatando-o em uma sequência de caracteres, fazendo a substring com exceção dos dois últimos dígitos e concatenando em um '00'"
Caius Jard
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.