J'ai fait une convert(varchar,datefield,112)
sur chaque champ de date que j'utilise dans les requêtes 'entre' dans SQL Server pour m'assurer que je ne comptabilise que les dates et n'en manque aucune en fonction de la partie heure de champs datetime.
Maintenant, j'entends que les convertis ne sont pas indexables et qu'il existe de meilleures méthodes, dans SQL Server 2005, pour comparer la partie date des heures dans une requête pour déterminer si les dates se situent dans une plage.
Quelle est la méthode optimale et indexable de faire quelque chose comme ceci:
select * from appointments
where appointmentDate>='08-01-2008' and appointmentDate<'08-15-2008'
La conversion de types numériques en valeurs de chaîne (un type de boxe) n'est pas la méthode la plus performante pour faire ce que vous recherchez. Ce n'est pas vraiment indexable, car le type de colonne réel est la date et l'heure.
Si vous recherchez la meilleure façon de rechercher des dates, votre exemple est exact, mais vous voudrez peut-être prendre en compte la différence de précision de 3 ms dans MSSQL. Cela peut signifier que les enregistrements d'une journée peuvent apparaître dans le résultat d'une autre journée.
Cette
select * from appointments where appointmentDate>='08-01-2008' and appointmentDate<'08-15-2008'
Devrait être ceci
select * from appointments where appointmentDate>='08-01-2008' and appointmentDate<='08-14-2008 23:59:59.996'
La meilleure façon de supprimer la partie temporelle d'un champ datetime est d'utiliser les fonctions datiff et dateadd.
DateAdd(day, datediff(day,0, MydateValue), 0)
Cela profite du fait que SQL Server stocke les dates sous la forme de deux entiers, l'un représentant le nombre de jours depuis le jour "0" 1er janvier 1900) et le second qui représente le nombre de --- (( ticks (chaque tick est d'environ 3,33 ms) depuis minuit (pour l'heure) *.
la formule ci-dessus doit simplement lire le premier entier. Aucune conversion ou traitement n'est requis, il est donc extrêmement rapide.
Pour que vos requêtes utilisent un index ... utilisez d'abord cette formule sur les paramètres de filtrage d'entrée, ou sur "l'autre" du signe égal du champ date et heure des tables, afin que l'optimiseur de requête n'ait pas à exécuter le calcul sur chaque champ datetime de la table pour déterminer quelles lignes satisfont le prédicat de filtre. Cela rend votre argument de recherche "capable de SARG" (ARGument de recherche)
Where MyDateTimeColumn > DateAdd(day,
datediff(day,0, @MydateParameter), 0) -- SARG-able
plutôt que
Where DateAdd(day, datediff(day,0,
MyDateTimeColumn ), 0) > @MydateParameter -- Not SARG-able
* REMARQUE. En interne, le deuxième entier (la partie temporelle) stocke les ticks. Dans une journée, il y a 24 x 60 X 60 X 300 = 25 920 000 ticks (par hasard juste en dessous de la valeur maximale qu'un entier 32 bits peut contenir). Cependant, vous n'avez pas à vous en préoccuper lors de la modification arithmétique d'un datetime ... Lorsque vous ajoutez ou soustrayez des valeurs des datetimes, vous pouvez traiter la valeur comme une fraction comme si elle était exactement égale à la partie fractionnaire d'une journée, comme si le la valeur datetime complète était un nombre à virgule flottante composé d'une partie entière représentant la date et la partie fractionnaire représentant l'heure). c'est à dire.,
`Declare @Dt DateTime Set @Dt = getdate()
Set @Dt = @Dt + 1.0/24 -- Adds one hour
Select @Dt
Set @Dt = @Dt - .25 -- Moves back 6 hours
Select @Dt`
C'est correct - faire la conversion exécutera la conversion pour chaque ligne interrogée. Il est préférable de laisser les colonnes de date en tant que dates et de passer vos clauses where en tant que dates:
select * from appointments where appointmentdate between
'08/01/2008' AND '08/16/2008'
Remarque: Le fait de laisser l'heure signifie minuit (00: 00.000), donc vous inclurez toutes les heures pour le 01/08, et toutes les heures pour le 15/08, et tout ce qui est exactement le 16/08/2008 00:00:00
Demandez à une colonne persistante calculée de calculer l'expression dont vous avez besoin. Si les colonnes sont calculées et persistantes, elles peuvent également être indexées.
Il y a aussi la manière décrite sur http://www.stillnetstudios.com/comparing-dates-without-times-in-sql-server/
SELECT CAST(FLOOR(CAST( getdate() AS float )) AS datetime)