Principale utente con più risposte
I misteri dei filtri sulle date

Domanda
-
Ciao a tutti,
dovrei realizzare una select che, prendendo in input una data senza ora (ad es: '2011-11-21') mi estragga solo i record di una tabella che soddisfino questi requisiti:- Questa data si sovrapponga, anche solo parzialmente, tra due campi DataInizioMonitoraggio e DataFineMonitoraggio (di tipo DateTime completo) presenti in una tabella
- Il cui giorno si strettamente minore al giorno del campo DataInizioMonitoraggio.
Faccio un esempio:
CREATE TABLE [dbo].[Valore](
[ID] [int] IDENTITY(1,1) NOT NULL,
[DataInizioMonitoraggio] [datetime] NULL,
[DataFineMonitoraggio] [datetime] NULL,
[Valore] [decimal](18, 3) NULL,
CONSTRAINT [PK_Valore] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]GO
-- Inserisco dati di prova
INSERT [dbo].[Valore]
([DataInizioMonitoraggio]
,[DataFineMonitoraggio]
,[Valore])
VALUES
('2011-11-20 12:30:00','2011-11-20 18:30:00',9),
('2011-11-19 12:30:00','2011-11-20 18:30:00',7),
('2011-11-01 12:30:00','2011-11-10 18:30:00',5),
('2011-10-20 12:30:00','2011-10-21 18:30:00',5),
('2011-09-20 12:30:00','2011-11-03 00:30:00',43),
('2010-12-31 19:30:00','2011-01-01 18:30:00',20),
('2011-10-10 12:30:00','2011-10-31 18:30:00',9),
('2011-10-22 00:30:00','2011-10-25 18:30:00',10)Se ora faccio:
DECLARE @DataRiferimento DATETIME = '2011-10-22'
SELECT * FROM dbo.Valore
WHERE @DataRiferimento BETWEEN DataInizioMonitoraggio AND DataFineMonitoraggioMi restituisce solo i record:
ID DataInizioMonitoraggio DataFineMonitoraggio Valore
5 2011-09-20 12:30:00.000 2011-11-03 00:30:00.000 43.000
7 2011-10-10 12:30:00.000 2011-10-31 18:30:00.000 9.000
Escludendo quindi l'ultimo, ovvero'2011-10-22 00:30:00','2011-10-25 18:30:00',10
che invece avrebbe dovuto estrarre, dato che gli passo la data del 22 ottobre, e quel record parte appunto dal 22 ottobre per terminare il 25.
Rimane poi il problema di trovare solo quelli che hanno il giorno strettamente inferiore.
Ad es. se con la prima passata (solo il filtro between) otterrei:
ID DataInizioMonitoraggio DataFineMonitoraggio Valore
5 2011-09-20 12:30:00.000 2011-11-03 00:30:00.000 43.000
7 2011-10-10 12:30:00.000 2011-10-31 18:30:00.000 9.000
8 2011-10-22 00:30:00,'2011-10-25 18:30:00',10
con il secondo filtro dovre ottenere solo i primi due record, dato che il terzo ha il giorno di DataInizio (22 ottobre) non "strettamente" minore di quello che gli ho passato.Qualcuno può darmi una mano?
Grazie.
Luigi
Risposte
-
con il secondo filtro dovre ottenere solo i primi due record, dato che il terzo ha il giorno di DataInizio (22 ottobre) non "strettamente" minore di quello che gli ho passato.
Intendevi qualcosa del genere?USE tempdb; CREATE TABLE dbo.Valore( ID int IDENTITY NOT NULL, DataInizioMonitoraggio datetime NULL, DataFineMonitoraggio datetime NULL, Valore decimal(18, 3) NULL, CONSTRAINT PK_Valore PRIMARY KEY(ID) ); INSERT dbo.Valore(DataInizioMonitoraggio, DataFineMonitoraggio, Valore) VALUES ('2011-11-20 12:30:00', '2011-11-20 18:30:00', 9) , ('2011-11-19 12:30:00', '2011-11-20 18:30:00', 7) , ('2011-11-01 12:30:00', '2011-11-10 18:30:00', 5) , ('2011-10-20 12:30:00', '2011-10-21 18:30:00', 5) , ('2011-09-20 12:30:00', '2011-11-03 00:30:00', 43) , ('2010-12-31 19:30:00', '2011-01-01 18:30:00', 20) , ('2011-10-10 12:30:00', '2011-10-31 18:30:00', 9) , ('2011-10-22 00:30:00', '2011-10-25 18:30:00', 10); DECLARE @DataRiferimento date = '2011-10-22'; SELECT * FROM dbo.Valore WHERE CAST(DataInizioMonitoraggio AS date) < @DataRiferimento AND DataFineMonitoraggio >= @DataRiferimento; /* Output: ID DataInizioMonitoraggio DataFineMonitoraggio Valore ----------- ----------------------- ----------------------- ------- 5 2011-09-20 12:30:00.000 2011-11-03 00:30:00.000 43.000 7 2011-10-10 12:30:00.000 2011-10-31 18:30:00.000 9.000 (2 row(s) affected) */ DROP TABLE dbo.Valore;
Quindi, DataInizioMonitoraggio (alle ore 00:00) deve essere antecedente, mentre DataFineMonitoraggio deve essere successiva o uguale a quella di riferimento.Ciao!
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo
http://social.technet.microsoft.com/Forums/it-IT/sqlserverit- Contrassegnato come risposta Ciupaz lunedì 21 novembre 2011 15:50
Tutte le risposte
-
Escludendo quindi l'ultimo, ovvero
'2011-10-22 00:30:00','2011-10-25 18:30:00',10
che invece avrebbe dovuto estrarre, dato che gli passo la data del 22 ottobre, e quel record parte appunto dal 22 ottobre per terminare il 25.
Ciao Luis,
Invece no in quanto la tua data è relativa alla mezzanotte del 22 ottobre, mentre quella riga è successiva e quindi non soddisfa il criterio di ricerca.
Rimane poi il problema di trovare solo quelli che hanno il giorno strettamente inferiore.
Ad es. se con la prima passata (solo il filtro between) otterrei:
ID DataInizioMonitoraggio DataFineMonitoraggio Valore
5 2011-09-20 12:30:00.000 2011-11-03 00:30:00.000 43.000
7 2011-10-10 12:30:00.000 2011-10-31 18:30:00.000 9.000
8 2011-10-22 00:30:00,'2011-10-25 18:30:00',10
con il secondo filtro dovre ottenere solo i primi due record, dato che il terzo ha il giorno di DataInizio (22 ottobre) non "strettamente" minore di quello che gli ho passato.
Non ho capito cosa intendi con "strettamente" minore. Puoi essere più chiaro? Se vuoi ottenere le prime due righe allora va bene la tua query ;-)Ciao!
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo
http://social.technet.microsoft.com/Forums/it-IT/sqlserverit -
con il secondo filtro dovre ottenere solo i primi due record, dato che il terzo ha il giorno di DataInizio (22 ottobre) non "strettamente" minore di quello che gli ho passato.
Intendevi qualcosa del genere?USE tempdb; CREATE TABLE dbo.Valore( ID int IDENTITY NOT NULL, DataInizioMonitoraggio datetime NULL, DataFineMonitoraggio datetime NULL, Valore decimal(18, 3) NULL, CONSTRAINT PK_Valore PRIMARY KEY(ID) ); INSERT dbo.Valore(DataInizioMonitoraggio, DataFineMonitoraggio, Valore) VALUES ('2011-11-20 12:30:00', '2011-11-20 18:30:00', 9) , ('2011-11-19 12:30:00', '2011-11-20 18:30:00', 7) , ('2011-11-01 12:30:00', '2011-11-10 18:30:00', 5) , ('2011-10-20 12:30:00', '2011-10-21 18:30:00', 5) , ('2011-09-20 12:30:00', '2011-11-03 00:30:00', 43) , ('2010-12-31 19:30:00', '2011-01-01 18:30:00', 20) , ('2011-10-10 12:30:00', '2011-10-31 18:30:00', 9) , ('2011-10-22 00:30:00', '2011-10-25 18:30:00', 10); DECLARE @DataRiferimento date = '2011-10-22'; SELECT * FROM dbo.Valore WHERE CAST(DataInizioMonitoraggio AS date) < @DataRiferimento AND DataFineMonitoraggio >= @DataRiferimento; /* Output: ID DataInizioMonitoraggio DataFineMonitoraggio Valore ----------- ----------------------- ----------------------- ------- 5 2011-09-20 12:30:00.000 2011-11-03 00:30:00.000 43.000 7 2011-10-10 12:30:00.000 2011-10-31 18:30:00.000 9.000 (2 row(s) affected) */ DROP TABLE dbo.Valore;
Quindi, DataInizioMonitoraggio (alle ore 00:00) deve essere antecedente, mentre DataFineMonitoraggio deve essere successiva o uguale a quella di riferimento.Ciao!
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo
http://social.technet.microsoft.com/Forums/it-IT/sqlserverit- Contrassegnato come risposta Ciupaz lunedì 21 novembre 2011 15:50
-