none
I misteri dei filtri sulle date RRS feed

  • 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 DataFineMonitoraggio

    Mi 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

     

    lunedì 21 novembre 2011 08:34

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
    lunedì 21 novembre 2011 14:47
    Moderatore

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
    lunedì 21 novembre 2011 14:34
    Moderatore
  • 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
    lunedì 21 novembre 2011 14:47
    Moderatore
  • Esatto, grazie Lorenzo.
    Meno male che ora c'è il tipo dato "Date" che mi esclude ore/minuti/secondi.
    In questo modo posso giocare solo sulla data intera.

    Luigi

    lunedì 21 novembre 2011 15:50