2010-04-06 15 views
33

In SQL 2005, invece di costruire una query da dateparts anno, mese e giorno,fila arrivare dove colonna datetime = oggi - Server SQL niubbo

c'è un modo più succinta di scrivere la clausola dove?

+0

Mi chiedo se una delle risposte sia più succinta di questa. Trovo questo anche più leggibile. dove (DATEPART (yy, myColum) = '2010') AND (DATEPART (mm, myColum) = '4') AND (DATEPART (dd, myColum) = '7'); – Chin

+1

** @ Chin, il tuo metodo impedirà l'utilizzo dell'indice e comporterà una scansione lenta della tabella. ** Ti consiglio vivamente di non eseguire MAI la ricerca in base a una data utilizzando tale metodo. È necessario "floor" le date nell'intervallo e non applicare alcuna funzione alla colonna se si desidera utilizzare un indice. questo è come pavimentare un datetime: http://stackoverflow.com/questions/85373/floor-a-date-in-sql-server –

+0

@KM, grazie per questo. Ho pensato di chiedere e vedere se ero fuori base. Attualmente non sono a conoscenza di un indice su questa colonna. Terrò questo a mente e pianifico le mie date come mi hai suggerito. – Chin

risposta

22

In SQL 2000 e SQL 2005 è possibile utilizzare una bella dichiarazione prescelta per rimuovere il componente tempo da un DateTime, cioè

SELECT DATEADD(dd, DATEDIFF(dd,0,GETDATE()), 0) 

tornerà 6 -Apr-2010 (bene solo per oggi).

Così combinata con la risposta di marc_s, che ci si vuole

SELECT (list of fields) 
FROM dbo.YourTable 
WHERE dateValue BETWEEN DATEADD(dd, DATEDIFF(dd,0,'MY Date and Time, But I Only Want Date'), 0) 
AND DATEADD(dd, DATEDIFF(dd,0,'MY Date and Time, But I Only Want Date'), 1) 

Edit: modificata a piacere, notare il 1 nel secondo DateAdd (questo aggiunge i giorni è stato fin dall'inizio a 1 (invece di 0), il che rende 7 Aprile 2010 00:00:00) Se si vuole 6 aprile 23:59:59 si prende un secondo di distanza dalla seconda data

DATEADD(ss,-1,'My DateTime') 

Final Call sarebbe diventato

DATEADD(ss,-1,DATEADD(dd, DATEDIFF(dd,0,'MY Date and Time, But I Only Want Date'), 1)) 

Ok questo è un sacco di informazioni in una volta! Spero che tutto ha un senso :)

+0

Mi piace la tua espressione per ottenere la parte solo per la data migliore della mia soluzione - ma questa selezione non funzionerà, no ?? Se si dispone di '2010-04-06 15:15:15' - come si confronta che solo per la parte di data andando a selezionare quella ?? Penso che tu abbia bisogno di un 'WHERE dateVALue BETWEEN (oggi) AND (oggi + 1 giorno)' tipo di selezione per afferrare tutti quei valori oggi con qualsiasi porzione di tempo ad essi associata .... –

+1

Se vuoi distruggere completamente gli indici , potresti usare DateAdd/DatePart sul DateValue, ma è una cattiva idea! (Se hai buoni indici :)) – PostMan

+0

Ho avuto tempi che sono tra 23: 59: 59.000 e 00: 00: 00.000 il giorno successivo eliminati dai rapporti. quindi non userei mai il "sottrarre un secondo metodo". È meglio mantenere l'ora alle 00: 00: 000.000 e incrementare un giorno e utilizzare "<" meno di (yourColumn

25

Su SQL Server 2008, si avrebbe un nuovo tipo di dati DATE, che si potrebbe usare per raggiungere questo obiettivo:

SELECT (list of fields) 
FROM dbo.YourTable 
WHERE dateValue BETWEEN 
    CAST(GETDATE() AS DATE) AND DATEADD(DAY, 1, CAST(GETDATE() AS DATE)) 

Il CAST(GETDATE() AS DATE) getta la data e l'ora correnti per un valore di data-only, per esempio restituire '2010-04-06' per il 6 aprile 2010. L'aggiunta di un giorno a tale selezione seleziona fondamentalmente tutti i valori datetime di oggi.

In SQL Server 2005, non c'è un modo semplice per farlo - la soluzione più elegante I found here sta usando la manipolazione numerica del DATETIME per ottenere lo stesso risultato:

SELECT (list of fields) 
FROM dbo.YourTable 
WHERE dateValue BETWEEN 
    CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME) AND 
    DATEADD(DAY, 1, CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)) 
+0

@marc_s - hai appena cancellato la tua risposta? mi ha spaventato mentre stavo cercando di aggiungere un commento. Se solo bevo aggiornamento. Grazie per il tuo aiuto anche se molto apprezzato. – Chin

+0

@Chin: sì, ho avuto prima una risposta stupida, l'ho cancellata, l'ho modificata e l'ho nuovamente cancellata :-) –

+0

@marc_s: hai sicuramente una definizione squilibrata della parola "elegante", +1 :) –

1

Qualcosa sulla falsariga di questo

CONVERT(date,tbldata.date)=CONVERT(date,getdate()) 

Ciò presuppone che la colonna della data includa anche l'ora. Se non, allora si può cambiare a

tbldata.date=CONVERT(date,getdate()) 
+0

Sql Server 2005 ha un tipo 'date'? ;) –

+0

Si scopre che non è così. Il mio stack attuale è SQL Server 2008, è passato un po 'di tempo da quando abbiamo aggiornato e ho pensato che il 2005 avesse questa caratteristica. –

4

Non buone prestazioni, ma una soluzione:

SELECT * 
FROM tblDate 
WHERE CONVERT(VARCHAR, date, 112) = CONVERT(VARCHAR, GETDATE(), 112); 

Se si tratta di una query comune una colonna calcolata deve essere aggiunto con un contenuto unico anno-mese-giorno.

+0

se si è corretti, sarà lento, perché non verrà utilizzato alcun indice –

0

ho usato un UDF per fare questo su colonne datetime risalenti a SQL 2000.

CREATE FUNCTION [dbo].[GETDATENOTIME](@now datetime) 
RETURNS smalldatetime 
AS 
BEGIN 
    RETURN (CONVERT(smalldatetime, CONVERT(varchar, @now, 112))) 
END 

Usage:

DECLARE @date smalldatetime 
SET @date = '4/1/10' 
SELECT * FROM mytable WHERE dbo.GETDATENOTIME(date) = @date 

Non è la cosa più efficiente al mondo (YMMV a seconda il tuo tavolo) ma fa il lavoro.Per le tabelle in cui so che selezionerò in base a data-senza-tempo molto, avrò una colonna specifica per questo con un set predefinito su dbo.GETDATENOTIME (GETDATE()).

+1

se hai mai avuto un indice sulla colonna "data", questo sicuramente non sarà in grado di usarlo e quindi si tradurrà in una scansione della tabella .... –

+0

Quindi il mio disclaimer alla fine. L'OP ha chiesto sintassi concisa, quindi questa è la risposta che gli ho dato. – Dane

Problemi correlati