Come posso selezionare il primo giorno del mese in SQL?


308

Devo solo selezionare il primo giorno del mese di una determinata variabile datetime.

So che è abbastanza facile fare questo tipo di codice:

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

Ma questo non è molto elegante, e probabilmente neanche molto veloce.

C'è un modo migliore per farlo? Sto usando SQL Server 2008.

Risposte:


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


63
Va notato che il bug citato da Martin Smith può "solo" influenzare le prestazioni, non la correttezza.
Olson.dev,


34
Nel caso qualcuno si stia chiedendo SELECT EOMONTH(@mydate) AS EndOfMonthti darà l'ultimo giorno del mese.
Hallizh,

3
Come posso determinare se il bug di stima della cardinalità notato mi influenzerà? È contrassegnato come riparato nel 2010. Ciò significa che solo SQL Server 2012 e versioni successive sono sicuri o è possibile che un server 2008 sia stato patchato?
Jon,

134

Oltre a tutte le risposte di cui sopra, un modo basato su una funzione introdotta in sql 2012

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


14

Il cast di una stringa (ovvero "5/1/2009") in datetime è sicuramente più leggibile, ma abbiamo trovato un codice un po 'di tempo fa che restituiva il primo del mese ...

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

10

Query semplice:

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

6

Probabilmente è abbastanza veloce. Perché non crearlo come funzione 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

Funziona anche questo:

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

3

Per favore usa questo

  1. Per Server 2012

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

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

3

Primo e ultimo giorno del mese corrente:

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

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

Soluzione davvero semplice ed elegante, ma tieni presente che questo restituisce anche la porzione di tempo della data se specificata nella variabile.
Kuklei,

Non sono riuscito a farlo funzionare. Oltre la parentesi di chiusura in più, ottengo questo errore: Operand type clash: date is incompatible with int. Immagino sia perché stai cercando di utilizzare l' -operatore in una data?
Sam,

Non so quanto sia buono in termini di prestazioni, ma sicuramente fa il suo lavoro.
salcoin,

@Sam, hai uno scontro perché l'aritmetica semplice (+, -) funziona su orari dei dati, non sulle date.
darlove l'

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

Ma l'OP sta cercando il primo giorno del mese. Per l'ultimo giorno, potresti semplicemente usare EOMONTH () - è così dal 2012.
deutschZuid


1

Googler futuri, su MySQL, prova questo:

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

3
Questa è una sql-serverdomanda date_sube lo intervalsono mysql.
OGHaza,

Bene, punto, ho modificato la risposta. Penso che sia ancora rilevante per il thread.
Ariel T,

1

Ho usato GETDATE () come data con cui lavorare, puoi sostituirlo con la data di cui hai bisogno.
Ecco come funziona: per prima cosa formattiamo la data nel formato AAAAMMGG ... troncando per mantenere solo i 6 caratteri più a sinistra per mantenere solo la porzione AAAAMM, quindi aggiungiamo '01' come il mese - e voilà! hai il primo giorno del mese corrente.

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

A proposito, le prestazioni sono eccezionali!


1

Se lo stai guardando oggi e usando SQL Server 2012 o versioni successive hai la funzione EOMONTH che semplifica le cose:

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

Puoi cambiare GETDATE () con qualunque variabile data tu voglia.


1

Qui possiamo usare la query seguente per la prima data del mese e l'ultima data del mese.

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

1

Se si utilizza SQL Server 2012 o versioni successive;

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

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

Il -2 ti porterà il primo giorno del mese scorso. cioè, getdate () è il 15/10/18. I tuoi risultati sarebbero il 01/09/18. Passare a -1 e i risultati saranno 10/1/18. 0 sarebbe l'inizio del mese prossimo, 01/11/2018 .. ecc. Ecc.

o

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

1

Prova a eseguire la seguente query:

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


0

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

Questa funzione ti fornirà la data parte della data di inizio del mese


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

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

Se non si desidera l'ora, convertirla in DATA o se si desidera impostare l'ora in 0:00:00, convertire in DATA e quindi di nuovo in DATA.

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

Cambia GETDATE () nella data desiderata


0

Personalmente ho raccomandato che il sql qui sotto perché quando provo ad usare la funzione di data nella clausola condition, rallenta molto la mia velocità di query.

comunque sentitevi liberi di provare questo.

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

0

Non competere con nessuna delle grandi menti qui, ma un semplice suggerimento leggermente diverso dalla risposta accettata sopra.

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

0

Mi piace usare FORMAT, puoi anche specificare un orario

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

0

In SQL Server 2012,

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

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

0

Questa query dovrebbe funzionare molto bene su MySQL:

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

0

Per chiunque sia ancora alla ricerca di una risposta, questo funziona come un fascino e elimina qualsiasi dateadds. Il timestamp è facoltativo, nel caso in cui debba essere specificato, ma funziona anche senza.

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

0

Ottieni la prima data e l'ultima data nella data che passiamo come parametro in 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

Ecco come lo faresti in MySQL:

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

4
Si prega di specificare che questa non è una risposta SQL Server ma funziona solo su MySQL.
Kuklei,

Per SQL Server, è possibile utilizzareSELECT FORMAT(GETDATE(), 'yyyy-MM-01')
NASSER

Non incoraggiare le persone a formattare le date in stringhe solo per fare qualcosa che può e deve essere fatto numericamente. È come dire "puoi arrotondare un numero al 100 più vicino formattandolo in una stringa, sottostringendo tutti tranne le ultime due cifre e concatenando un '00'"
Caius Jard
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.