Datepart calcolo anni mesi e giorni tra due date

di il
6 risposte

Datepart calcolo anni mesi e giorni tra due date

Buongiorno

ho due campi [Periodo dal] e [Periodo al]  della tabella Dichiarazione, mi serve estrarre gli anni i mesi e i giorni . Es. ho lavorato dal 01.02.2025 al 06.02.2025, il risultato che devo ottenere è: 0 anni, 0 mesi , 6 giorni.

Ho creto le 3 colonne nella struttura query con le seguenti stinghe:

Anni: DateDiff("aaaa";[Periodo dal];[Periodo al])+(Format([Periodo al];"mmgg")<Format([Periodo dal];"mmgg"))

Mesi: Int((DateDiff("m";[Periodo dal];[Periodo al])+Int(Format([Periodo al];"gg")<Format([Periodo dal];"gg")))) Mod 12

Giorni: IIf(Day([Periodo dal])<=Day([Periodo al]);Format([Periodo al];"gg")-Format([Periodo dal];"gg");Day(DateSerial(Year([Periodo dal]);Month([Periodo dal])+1;0))-Day([Periodo dal])+Day([Periodo al]))+1

i risultati sono giusti e perfetti ma il problema per cui chiedo aiuto è che : se i due campi di origine sono vuoti (cioè il dipendente non ha mai lavorato prima) nel campo Giorno della query mi scrive errore, questo non mi permette di inserire in altra tabella i dati 0,0,0 e ne di estrarre un formato excel dei periodi.

ho trovato qui https://learn.microsoft.com/it-it/sql/t-sql/functions/datediff-transact-sql?view=sql-server-ver16 

questo , ma non riesco nemmeno a partire probabilmente per la mia poca esperienza: 

-- DOES NOT ACCOUNT FOR LEAP YEARS
DECLARE @date1 AS DATETIME, @date2 AS DATETIME, @result AS VARCHAR (100);

DECLARE @years AS INT, @months AS INT, @days AS INT, @hours AS INT, @minutes AS INT, @seconds AS INT, @milliseconds AS INT;

SET @date1 = '1900-01-01 00:00:00.000';

SET @date2 = '2018-12-12 07:08:01.123';

SELECT @years = DATEDIFF(yy, @date1, @date2);

IF DATEADD(yy, -@years, @date2) < @date1
   SELECT @years = @years - 1;

SET @date2 = DATEADD(yy, -@years, @date2);

SELECT @months = DATEDIFF(mm, @date1, @date2);

IF DATEADD(mm, -@months, @date2) < @date1
   SELECT @months = @months - 1;

SET @date2 = DATEADD(mm, -@months, @date2);

SELECT @days = DATEDIFF(dd, @date1, @date2);

IF DATEADD(dd, -@days, @date2) < @date1
   SELECT @days = @days - 1;

SET @date2 = DATEADD(dd, -@days, @date2);

SELECT @hours = DATEDIFF(hh, @date1, @date2);

IF DATEADD(hh, -@hours, @date2) < @date1
   SELECT @hours = @hours - 1;

SET @date2 = DATEADD(hh, -@hours, @date2);

SELECT @minutes = DATEDIFF(mi, @date1, @date2);

IF DATEADD(mi, -@minutes, @date2) < @date1
   SELECT @minutes = @minutes - 1;

SET @date2 = DATEADD(mi, -@minutes, @date2);

SELECT @seconds = DATEDIFF(s, @date1, @date2);

IF DATEADD(s, -@seconds, @date2) < @date1
   SELECT @seconds = @seconds - 1;

SET @date2 = DATEADD(s, -@seconds, @date2);

SELECT @milliseconds = DATEDIFF(ms, @date1, @date2);

SELECT @result = ISNULL(CAST (NULLIF (@years, 0) AS VARCHAR (10)) + ' years,', '')
   + ISNULL(' ' + CAST (NULLIF (@months, 0) AS VARCHAR (10)) + ' months,', '')
   + ISNULL(' ' + CAST (NULLIF (@days, 0) AS VARCHAR (10)) + ' days,', '')
   + ISNULL(' ' + CAST (NULLIF (@hours, 0) AS VARCHAR (10)) + ' hours,', '')
   + ISNULL(' ' + CAST (@minutes AS VARCHAR (10)) + ' minutes and', '')
   + ISNULL(' ' + CAST (@seconds AS VARCHAR (10)) + CASE
       WHEN @milliseconds > 0
       THEN '.' + CAST (@milliseconds AS VARCHAR (10))
       ELSE ''
   END + ' seconds', '');

SELECT @result;

6 Risposte

  • Re: Datepart calcolo anni mesi e giorni tra due date

    Quello che hai trovato è per SQLServer che supporta T-SQL ma non per JET, quindi leggi più attentamente.

    Quello che vuoi ottenere non è così banale, e non riuscirai facilmente ad ottenerlo in una Query senza scrivere una Funzione in VBA....

    Questo è un esempio, ma in rete troverai mille versioni :

    Public Function GetDateDiff(DOB As Date, AsOfD As Date) As String
        Dim d As Integer, m As Integer, y As Integer
        Dim dtBDay As Date
    
        If AsOfD >= DOB Then
            dtBDay = DateSerial(Year(AsOfD), Month(DOB), Day(DOB))
            y = DateDiff("yyyy", DOB, AsOfD) + (dtBDay > AsOfD)
            m = DateDiff("m", DOB, AsOfD) - y * 12 - IIf(Day(DOB) > Day(AsOfD), 1, 0)
            d = DateDiff("d", DateAdd("m", m, DateAdd("yyyy", y, DOB)), AsOfD)
            GetDateDiff = y & " year(s), " & m & " month(s) and " & d & " day(s)"
        End If
    
    End Function
  • Re: Datepart calcolo anni mesi e giorni tra due date

    Ciao Ake e @Alex

    un altra soluzione, ma dipende dai scenari, potrebbe utilizzare la funzione IsDate per determinare se esiste una data e se il suo valore è diverso da Null

    Per esempio se abbiamo una tabella con questi dati:

    si potrebbe realizzare una query di questo tipo:

    con  questi risultati:

    La stringa Sql può essere scritta in questo modo con il controllo delle date con la funzione IsDate:

    SELECT TblDateDalAL.ID, TblDateDalAL.[Periodo dal], TblDateDalAL.[Periodo al], 
    IIf(IsDate([Periodo dal]) And IsDate([Periodo al]),DateDiff("yyyy",[Periodo dal],[Periodo al]),0) AS Anni, 
    IIf(IsDate([Periodo dal]) And IsDate([Periodo al]),(DateDiff("m",[Periodo dal],[Periodo al]) Mod 12),0) AS Mesi, 
    IIf(IsDate([Periodo dal]) And IsDate([Periodo al]),IIf(Day([Periodo dal])<=Day([Periodo al]),Day([Periodo al])-Day([Periodo dal]),Day(DateSerial(Year([Periodo dal]),Month([Periodo dal])+1,0))-Day([Periodo dal])+Day([Periodo al])),0) AS Giorni
    FROM TblDateDalAL;
    

    Nota: non ho controllato la validità delle tue espressioni che ho riportato pari pari, ma ho solo aggiunto il controllo con la IsDate che in caso di date mancanti restituisce il valore = 0... insomma, tutto da valutare e validare.

  • Re: Datepart calcolo anni mesi e giorni tra due date

    Franco corretto nella sostanza fa più o meno la stessa cosa, non userei ISDATE, in quanto si può ipotizzare che i campi siano Date, la validazione del dato meglio affidarla alla fase di inserimento non in una Query per una questione di efficienza, ma magari verificherei se Data1>Data2

    Non mi piace mai scrivere calcoli di questo tipo nelle Query in quanto sei costretto ad affettuare più volte lo stesso calcolo non avendo variabili in cui memorizzare... sicchè, anche per capacità di fare Debug, preferisco funzioni esterne... tanto entrambe non sono portabili...

  • Re: Datepart calcolo anni mesi e giorni tra due date

    06/02/2025 - @Alex ha scritto:

    Non mi piace mai scrivere calcoli di questo tipo nelle Query in quanto sei costretto ad affettuare più volte lo stesso calcolo non avendo variabili in cui memorizzare...

    Si si si ... condivido ... pure io tendo soprattutto a semplificare scrivendo una funzione esterna da richiamare per i motivi da te riportati.

    Di gran lunga preferisco in certi scenari demandare ad una funzione esterna.

  • Re: Datepart calcolo anni mesi e giorni tra due date

    06/02/2025 - By65Franco ha scritto:

    Ciao Ake e @Alex

    un altra soluzione, ma dipende dai scenari, potrebbe utilizzare la funzione IsDate per determinare se esiste una data e se il suo valore è diverso da Null

    Per esempio se abbiamo una tabella con questi dati:

    si potrebbe realizzare una query di questo tipo:

    con  questi risultati:

    La stringa Sql può essere scritta in questo modo con il controllo delle date con la funzione IsDate:

    SELECT TblDateDalAL.ID, TblDateDalAL.[Periodo dal], TblDateDalAL.[Periodo al], 
    IIf(IsDate([Periodo dal]) And IsDate([Periodo al]),DateDiff("yyyy",[Periodo dal],[Periodo al]),0) AS Anni, 
    IIf(IsDate([Periodo dal]) And IsDate([Periodo al]),(DateDiff("m",[Periodo dal],[Periodo al]) Mod 12),0) AS Mesi, 
    IIf(IsDate([Periodo dal]) And IsDate([Periodo al]),IIf(Day([Periodo dal])<=Day([Periodo al]),Day([Periodo al])-Day([Periodo dal]),Day(DateSerial(Year([Periodo dal]),Month([Periodo dal])+1,0))-Day([Periodo dal])+Day([Periodo al])),0) AS Giorni
    FROM TblDateDalAL;
    

    Nota: non ho controllato la validità delle tue espressioni che ho riportato pari pari, ma ho solo aggiunto il controllo con la IsDate che in caso di date mancanti restituisce il valore = 0... insomma, tutto da valutare e validare.

    Grazie Franco sembra che faccia al mio caso da principiante provo nel pomeriggio , ero quasi arrivato al risultato che mi serviva a parte questo errore sui giorni, ma da dove comincio per diventare bravo come voi ? 

  • Re: Datepart calcolo anni mesi e giorni tra due date

    06/02/2025 - Ake ha scritto:

    Grazie Franco sembra che faccia al mio caso da principiante provo nel pomeriggio ,

    Ciao Ake

    Fermati !!!! quello che devi fare e renderti conto che i due sistemi ottengono lo stesso risultato e dei due devi approcciare il metodo migliore.

    Quindi abbiamo due esempi: 

    uno usa la IIF IsDate per determinare se stai operando effettivamente con delle date, altrimenti ritorna il valore 0

    il secondo usa una funzione dove puoi implementare eventuali controlli per validare le date e decidere in quale forma ritornare il risultato.

    Quindi, ora che ti sei reso conto, sceglierai ovviamente, senza ombra di dubbio, il metodo con la function in quanto molto più flessibile e plasmabile a tuo uso e consumo.

    ma da dove comincio per diventare bravo come voi ? 

    Appunto, devi iniziare a capire come interagire in certi particolari casi, con il Vba. In questo caso devi iniziare a pensare che le Query hanno delle funzioni predefinite e oltre a queste puoi crearti delle tue personali funzioni da poter richiamare allo stesso modo.
    Il mio consiglio è di tenere pulita il più possibile la struttura della query e iniziare a capire come scrivere una tua function in modo che possa essere utilizzata in una Query.  

Devi accedere o registrarti per scrivere nel forum
6 risposte