2014-08-29 11 views

risposta

36

se siete su SQL Server 2008 o versioni successive è possibile utilizzare la data tipo di dati:

SELECT * 
FROM [User] U 
WHERE CAST(U.DateCreated as DATE) = '2014-02-07' 

va notato che se colonna della data è indicizzata allora questo sarà ancora utilizzare l'indice ed è SARGabl e. Questo è un caso speciale per date e dati.

enter image description here

Si può vedere che SQL Server in realtà si trasforma questo in un> e < clausola:

enter image description here

Ho appena provato questo su un grande tavolo, con un secondario indice sulla colonna della data come per i commenti di @kobik e l'indice è ancora usato, questo non è il caso per gli esempi che usano BETWEEN o> = e <:

SELECT * 
FROM [User] U 
WHERE CAST(U.DateCreated as DATE) = '2016-07-05' 

showing index usage with secondary index

+0

potrebbe sembrare che io stavo prendendo di mira questa risposta, non è stato così come abbiamo pubblicato quasi nello stesso momento e non ero a conoscenza della tua risposta. Ma per ridurre la necessità di aumentare nuovamente la dimensione della tua immagine, ho cambiato il mio esempio "non fare", forse questo sarà di aiuto? –

+0

@Used_By_Already yes grazie –

+0

Come va il database 'AaronsBad', in questi giorni? –

59

non essere tentati di fare le cose in questo modo:

Select * from [User] U where convert(varchar(10),U.DateCreated, 120) = '2014-02-07' 

Questo è un modo migliore:

Select * from [User] U 
where U.DateCreated >= '2014-02-07' and U.DateCreated < dateadd(day,1,'2014-02-07') 

vedi: Sargable (la la pagina è stata rimossa da Wikipedia)

EDIT + Esistono due motivi fondamentali per evitare l'uso di funzioni sui dati nella clausola where (o nelle condizioni di join).

  1. Nella maggior parte dei casi utilizzando una funzione di dati per filtrare o partecipare rimuove la capacità del ottimizzatore per accedere ad un indice su quel campo, rendendo quindi la query lenta (o più "costose")
  2. L'altro è , per ogni riga di dati coinvolti è eseguito almeno un calcolo. Questo potrebbe aggiungere centinaia, migliaia o molti milioni di calcoli alla query in modo da poterli confrontare con un singolo criterio come 2014-02-07. È molto più efficiente modificare i criteri in base ai dati.

"modifica dei criteri in base ai dati" è il mio modo di descrivere "usare SARGABLE predicati"


E non usare tra una.

la migliore pratica con la data e l'ora intervalli è quello di evitare TRA ea usare sempre la forma:

DOVE col> = '20120101' e Col < '20.120.201' Questo modulo funziona con tutti i i tipi e tutte le precisioni, indipendentemente dal fatto che la parte temporale sia applicabile.

http://sqlmag.com/t-sql/t-sql-best-practices-part-2 (Itzik Ben-Gan)

+1

Se hai un po 'di tempo dovresti spiegare perché uno è migliore dell'altro (indice di utilizzo), ciò renderà questa una risposta migliore – Serpiton

+0

più facile a dirsi che a farsi, ci sono diversi tipi di dati (data, datetime, datetime2, smalldatetime) più diversi versioni di mssql da considerare. Una risposta non va bene per tutto ciò che ho paura. Ma aggiungerò una nota. –

+1

Se si utilizza il cast (datetime come data), verrà comunque utilizzato un indice nel campo datetime. Provalo. –

-2

È possibile utilizzare LIKE dichiarazione al posto di =. Ma per fare questo con DateStamp è necessario CONVERT prima a VARCHAR:

SELECT * 
FROM [User] U 
WHERE CONVERT(VARCHAR, U.DateCreated, 120) LIKE '2014-02-07%' 
+2

In primo luogo, dirò che "Oo oro lucido!" il favoritismo e una generale mancanza di buone maniere sono ogni tanto un problema qui. Secondo, in questa particolare istanza, @marc_s ha assolutamente ragione. È una buona abitudine non fare ipotesi su scenari marginali su come l'OP potrebbe voler eseguire operazioni su stringhe alla data, quando il costo di tale ipotesi è troppo grande per quanto riguarda le prestazioni, la leggibilità, la manutenibilità e le migliori pratiche generali. Questo è un posto dove scambiare esperienze. Ma per farlo, deve essere in grado di segnalare anche esperienze e metodologie negative o non raccomandate. – Kahn

+1

+1 dato che si tratta di soluzioni funzionanti e che possono essere utilizzate in molti scenari, per favore non scartare le risposte di lavoro solo perché ritieni che non sia una buona pratica, fornirci un articolo o un documento affidabile, quindi ci convinci altro – amd

+1

@Ahmad La conversione delle stringhe seguita dal confronto è più costosa del confronto delle date. Quindi i downvotes sono garantiti, in quanto questo non è un buon modo di fare ciò che l'OP vuole fare. – mbomb007

-1

Si prega di provare questo. Questa query può essere utilizzato per il confronto data

select * from [User] U where convert(varchar(10),U.DateCreated, 120) = '2014-02-07' 
2

Secondo la query Select * from [User] U where U.DateCreated = '2014-02-07'

SQL Server è il confronto la data e l'ora esatta cioè (a confronto con 2014-02-07 12:30:47.2202014-02-07 00:00:00.000 per l'uguaglianza). ecco perché il risultato del confronto è falso

Pertanto, durante il confronto delle date è necessario considerare anche il tempo. È possibile utilizzare
Select * from [User] U where U.DateCreated BETWEEN '2014-02-07' AND '2014-02-08'.

+2

Sfortunatamente SQL definisce 'between' con uguale a entrambe le estremità (> = e <=) ad es. 'seleziona * da x dove col_1 tra 'A' e 'M'' include A e M (più B a L ovviamente). Questa natura inclusiva di "tra" è terrificante per qualcosa come un indice di un documento; ma per intervalli di date/orari è un disastro perché crea sovrapposizioni. So che usare tra un aspetto e l'altro è fantastico, ma in realtà un 'SQL tra' non funziona correttamente per gli intervalli di date. Usa sempre una combinazione di> = con = '2014-02-07' e U.DateCreated <'2014-02-08'' –

+0

@Used_By_Already Accetto con te, ma per questo caso particolare (in questione), 'between' è OK. il tuo suggerimento di usare '> =' e '<' è senza dubbio preferibile tra '' per gli intervalli di date. Voglio solo dire che dovremmo prendere in considerazione il tempo anche quando confrontiamo le date. – imdzeeshan

Problemi correlati