Confronto di date in SQL Server

Un problema che si incontra spesso in SQL Server, quando bisogna effettuare delle query che effettuano il confronto su due campi di tipo DateTime, consiste nel fatto che SQL Server, oltre a memorizzare la data, memorizza anche l’orario.  Ad esempio una query del genere potrebbe dare questo tipo di risultato:

 

select Data1, Data2 from MiaTabella where Data1 <= Data2

 

Data1                   Data2

----------------------- -----------------------

2006-11-21 12:38:00     2006-11-23 17:18:00

2006-07-24 10:52:00     2006-07-24 10:52:00

 

A prima vista sembrerebbe corretto, ma c’è la possibilità che si verifichi un errore piuttosto subdolo.

Esistono diverse soluzioni al problema, quella che preferisco è quella di utilizzare la funzione DATEDIFF. Se correggiamo la query in questo modo ci accorgiamo subito di quale era l’errore della prima query.

 

select Data1, Data2 from MiaTabella where DATEDIFF(d, Data2, Data1) <= 0

 

Data1                   Data2

----------------------- -----------------------

2006-11-21 12:38:00     2006-11-23 17:18:00

2006-07-24 10:52:00     2006-07-24 10:52:00

2006-07-25 11:54:00     2006-07-25 11:53:00

 

Technorati Tags: ,

posted @ venerdì 24 novembre 2006 13:25

Print

Comments on this entry:

# re: Confronto di date in SQL Server

Left by Riccardo at 24/11/2006 14:42
Gravatar
Ho anche fatto S. Tommaso, ed ho fatoo la prova ed a me funziona perfettamente anche la prima query

# re: Confronto di date in SQL Server

Left by Daniele Proietti at 24/11/2006 14:55
Gravatar
Scusate ... nei copia ed incolla ho invertito due valori .... riprovate ;-)

# re: Confronto di date in SQL Server

Left by Alessandro Scardova at 24/11/2006 15:46
Gravatar
Aggiungo che la
> where DATEDIFF(d, Data2, Data1) <= 0
non è un mostro di performance: guardati il query plan

# re: Confronto di date in SQL Server

Left by Davide Mauri at 24/11/2006 15:59
Gravatar
Daniele, ho scritto 3 articoli sull'argomento:

http://blogs.ugidotnet.org/nettools/articles/9541.aspx
http://blogs.ugidotnet.org/nettools/articles/9560.aspx
http://blogs.ugidotnet.org/nettools/articles/40144.aspx

Credo che ti saranno utili. Inoltre come dice Alessandro è meglio non applicare funzioni sulle colonne usate come clausole di ricerca altrimenti costringi SQL a fare uno scan al posto che un seek.

# re: Confronto di date in SQL Server

Left by Daniele Proietti at 24/11/2006 16:12
Gravatar
Questo è lo script utilizzato:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MiaTabella](
[id] [int] IDENTITY(1,1) NOT NULL,
[Data1] [datetime] NULL,
[Data2] [datetime] NULL
) ON [PRIMARY]

insert into [dbo].[MiaTabella] values ('20061121 12:38:00', '20061123 17:18:00')
insert into [dbo].[MiaTabella] values ('20060724 10:52:00', '20060724 10:52:00')
insert into [dbo].[MiaTabella] values ('20060725 11:54:00', '20060725 11:53:00')

select Data1, Data2 from MiaTabella where Data1 <= Data2
select Data1, Data2 from MiaTabella where DATEDIFF(d, Data2, Data1) <= 0

Davide, grazie per la segnalazione agli articoli che sono molto interessanti, io però mi stavo riferendo ad un confronto fra due campi esistenti (in cui è presente anche l'orario) e non a dei valori di input. So che le performance non sono eccezionali, ma per questa situazione non vedo soluzioni migliori.
Se qualcuno ha qualche suggerimento ....

# re: Confronto di date in SQL Server

Left by Daniele Proietti at 24/11/2006 17:05
Gravatar
Nel caso specifico debbo ottenere tutte le righe in cui Data1 si riferisce ad un giorno uguale od inferiore a Data2

# re: Confronto di date in SQL Server

Left by Davide Mauri at 25/11/2006 20:17
Gravatar
Se non è possibile limitare la ricerca fino ad un data o da una data in poi in effetti SQL Server è costretto a fare uno scan della tabella o dell'indice cluster.

Con SQL 2005 però l'optimzer è molto più intelligente che in passato e benficia maggiormente di indici costruiti su colonne calcolate.

Aggiungendo una colonna colcolata indicizzata

alter table [dbo].[MiaTabella]
add Diff as DATEDIFF(d, Data2, Data1)

create index IX_Test2 on [dbo].[MiaTabella] (Diff)

Queste due query effettuano un seek anziche uno scan.

select Data1, Data2 from MiaTabella where DATEDIFF(d, Data2, Data1) <= 0
select Data1, Data2 from MiaTabella where diff <= 0

# re: Confronto di date in SQL Server

Left by Daniele Proietti at 16/01/2008 05:09
Gravatar
Il tuo caso è abbastanza semplice:
select * from dbo.Orders
where OrderDate >= '1996-08-01' and
OrderDate < '1996-09-01'

In questo caso prende tutte le righe relative al mese di agosto 1996.
Comments have been closed on this topic.
«aprile»
domlunmarmergiovensab
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011