2009-06-23 36 views
5

Nella mia tabella ho un campo Month (minuscolo) e un giorno (minuscolo). Mi piacerebbe avere una funzione che richiede questo mese e giorno e produce un datetime per la prossima data (incluso l'anno) dato questo mese e giorno.

Quindi se avessi mese = 9, giorno = 7, produrrebbe il 9/7/2009.
Se avessi il mese 1, il giorno 1 produrrebbe 1/1/2010.SQL: Come produrre la data successiva data mese e giorno

+0

come si fa a sapere che anno da usare? Stai solo partendo dal presupposto che sarà sempre basato sulla data corrente? Inoltre, quale database stai usando? – northpole

+0

Si basa su oggi. Quindi diciamo oggi è 23/6/2009. La data nella tabella è mese = 6, giorno = 22. Quindi voglio che restituisca il 22/06/2010 perché quella è la prossima data. –

risposta

2

qualcosa di simile avrebbe funzionato. È una variante del tuo metodo, ma non usa il formato letterale MM/GG/AAAA, e non esploderà contro input negativi (nel bene o nel male).

declare @month tinyint 
declare @day tinyint 
set @month = 9 
set @day = 1 

declare @date datetime 

-- this could be inlined if desired 
set @date = convert(char(4),year(getdate()))+'0101' 
set @date = dateadd(month,@month-1,@date) 
set @date = dateadd(day,@day-1,@date) 

if @date <= getdate()-1 
    set @date = dateadd(year,1,@date) 

select @date 

In alternativa, per creare una stringa in formato YYYYMMDD:

set @date = 
    right('0000'+convert(char(4),year(getdate())),4) 
+ right('00'+convert(char(2),@month),2) 
+ right('00'+convert(char(2),@day),2) 

Un altro metodo, che evita letterali insieme:

declare @month tinyint 
declare @day tinyint 
set @month = 6 
set @day = 24 

declare @date datetime 
declare @today datetime 

-- get todays date, stripping out the hours and minutes 
-- and save the value for later 
set @date = floor(convert(float,getdate())) 
set @today = @date 

-- add the appropriate number of months and days 
set @date = dateadd(month,@month-month(@date),@date) 
set @date = dateadd(day,@day-day(@date),@date) 

-- increment year by 1 if necessary 
if @date < @today set @date = dateadd(year,1,@date) 

select @date 
1

Ecco il mio esempio SQL finora. Non mi piace molto, però ...

DECLARE @month tinyint, 
    @day tinyint, 
    @date datetime 

SET @month = 1 
SET @day = 1 

-- SET DATE TO DATE WITH CURRENT YEAR 
SET @date = CONVERT(datetime, CONVERT(varchar,@month) + '/' + CONVERT(varchar,@day) + '/' + CONVERT(varchar,YEAR(GETDATE()))) 


-- IF DATE IS BEFORE TODAY, ADD ANOTHER YEAR 
IF (DATEDIFF(DAY, GETDATE(), @date) < 0) 
BEGIN 
    SET @date = DATEADD(YEAR, 1, @date) 
END 

SELECT @date 
+2

Non utilizzare il formato MM/GG/AAAA per i valori letterali delle date. Utilizzare invece YYYYMMDD. Eviterà problemi di localizzazione e ordinerà correttamente. –

+0

Altrimenti, non vedo alcun problema con il tuo metodo. Non ti piace la conversione da un letterale? –

+0

Sembra che ci dovrebbe essere una soluzione facile a. –

1

Ecco una soluzione con PostgreSQL

your_date_calculated = Year * 10000 + Month * 100 + Day 

ti dà una data come 20090623.

select cast(cast(your_date_calculated as varchar) as date) + 1 
1

Ecco la mia versione. Il nucleo di esso è appena due righe, utilizzando la funzione DATEADD, e non richiede alcuna conversione da/per le stringhe, galleggianti o qualsiasi altra cosa:

DECLARE @Month TINYINT 
DECLARE @Day TINYINT 

SET @Month = 9 
SET @Day = 7 

DECLARE @Result DATETIME 

SET @Result = 
    DATEADD(month, ((YEAR(GETDATE()) - 1900) * 12) + @Month - 1, @Day - 1) 
IF (@Result < GETDATE()) 
    SET @Result = DATEADD(year, 1, @Result) 

SELECT @Result 
+0

Bello. Che ne dici di una versione in linea per evitare il sovraccarico della chiamata di funzione? es. SELEZIONA DATEADD (anno, , DATEADD (mese, ((ANNO (GETDATE()) - 1900) * 12) + MonthField - 1, DayField - 1)) come NewDate FROM .... –

Problemi correlati