Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Convertir les champs datetime du serveur SQL pour comparer uniquement les parties de date, avec des recherches indexées

La meilleure façon de supprimer la partie heure d'un champ datetime consiste à utiliser les fonctions datediff 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 uniquement le premier entier. Il n'y a pas de conversion ou de traitement 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" côté du signe égal du champ date/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 "SARG-able" (Search ARGument)

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 de 32 bits peut contenir). Cependant, vous n'avez pas à vous en soucier lorsque vous modifiez arithmétiquement une date/heure... Lorsque vous ajoutez ou soustrayez des valeurs de dates/heures, vous pouvez traiter la valeur comme une fraction comme si elle était exactement égale à la partie fractionnaire d'un jour, comme si le la valeur datetime complète était un nombre à virgule flottante composé d'une partie entière représentant la date et d'une 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`