Comparer DATETIME et DATE en ignorant la partie de temps

151

J'ai deux tables où la colonne [date]est le type de DATETIME2(0).

Je dois comparer deux enregistrements uniquement par leurs parties de date (jour + mois + année), en supprimant les parties de temps (heures + minutes + secondes).

Comment puis je faire ça?

abatishchev
la source

Réponses:

252

Utilisez le CASTvers le nouveau DATEtype de données dans SQL Server 2008 pour comparer uniquement la partie date:

IF CAST(DateField1 AS DATE) = CAST(DateField2 AS DATE)
marc_s
la source
61

Un petit inconvénient dans la réponse de Marc est que les deux champs de date ont été typés, ce qui signifie que vous ne pourrez pas tirer parti des index.

Ainsi, s'il est nécessaire d'écrire une requête pouvant bénéficier d'un index sur un champ de date, alors l'approche (plutôt alambiquée) suivante est nécessaire.

  • Le champ de date indexé (appelez-le DF1) ne doit être touché par aucun type de fonction.
  • Vous devez donc comparer DF1 à la plage complète des valeurs datetime pour le jour de DF2.
  • Cela va de la partie date de DF2 à la partie date du jour après DF2.
  • C'est à dire (DF1 >= CAST(DF2 AS DATE)) AND (DF1 < DATEADD(dd, 1, CAST(DF2 AS DATE)))
  • REMARQUE : Il est très important que la comparaison soit > = (égalité autorisée) à la date de DF2, et (strictement) < le jour après DF2. De plus, l'opérateur BETWEEN ne fonctionne pas car il permet l'égalité des deux côtés.

PS: Un autre moyen d'extraire la date uniquement (dans les anciennes versions de SQL Server) consiste à utiliser une astuce sur la façon dont la date est représentée en interne.

  • Jetez la date comme un flotteur.
  • Tronquer la partie fractionnaire
  • Reconstituer la valeur à une date / heure
  • C'est à dire CAST(FLOOR(CAST(DF2 AS FLOAT)) AS DATETIME)
Désabusé
la source
5

Bien que j'aie voté pour la réponse marquée comme correcte. Je voulais aborder quelques points pour quiconque trébucherait là-dessus.

En général, si vous filtrez spécifiquement sur les valeurs de date uniquement. Microsoft recommande d'utiliser le format indépendant de la langue de ymdou y-m-d.

Notez que le formulaire «2007-02-12» est considéré comme indépendant de la langue uniquement pour les types de données DATE, DATETIME2 et DATETIMEOFFSET.

Faire une comparaison de dates en utilisant l'approche susmentionnée est simple. Prenons l'exemple artificiel suivant.

--112 is ISO format 'YYYYMMDD'
declare @filterDate char(8) = CONVERT(char(8), GETDATE(), 112)

select 
    * 
from 
    Sales.Orders
where
    CONVERT(char(8), OrderDate, 112) = @filterDate

Dans un monde parfait, toute manipulation de la colonne filtrée doit être évitée, car cela peut empêcher SQL Server d'utiliser efficacement les index. Cela dit, si les données que vous stockez ne concernent que la date et non l'heure, envisagez de les stocker comme DATETIMEavec minuit comme heure. Car:

Lorsque SQL Server convertit le littéral en type de colonne filtrée, il suppose minuit lorsqu'une partie de temps n'est pas indiquée. Si vous souhaitez qu'un tel filtre renvoie toutes les lignes à partir de la date spécifiée, vous devez vous assurer que vous stockez toutes les valeurs avec minuit comme heure.

Ainsi, en supposant que vous ne vous préoccupez que de la date, et stockez vos données en tant que telles. La requête ci-dessus peut être simplifiée pour:

--112 is ISO format 'YYYYMMDD'
declare @filterDate char(8) = CONVERT(char(8), GETDATE(), 112)

select 
    * 
from 
    Sales.Orders
where
    OrderDate = @filterDate
pimbrouwers
la source
3

Vous pouvez essayer celui-ci

CONVERT(DATE, GETDATE()) = CONVERT(DATE,'2017-11-16 21:57:20.000')

Je teste cela pour MS SQL 2014 en suivant le code

select case when CONVERT(DATE, GETDATE()) = CONVERT(DATE,'2017-11-16 21:57:20.000') then 'ok'
            else '' end
reza.cse08
la source
-3

Pour comparer deux dates telles que MM / JJ / AAAA à MM / JJ / AAAA . N'oubliez pas Le premier type de colonne de Field doit être dateTime. Exemple: columnName: date_paiement dataType: DateHeure .

après cela, vous pouvez facilement le comparer. La requête est:

select  *  from demo_date where date >= '3/1/2015' and date <=  '3/31/2015'.

C'est très simple ...... Il l'a testé .....

Pankaj
la source
Cela ne répond pas tout à fait à la question. Il interroge pendant un mois, pas un jour.
Curtis Yallop
Pour votre requête de mars: si la date est l'heure du 31/03/2015 à 13h00, elle ne sera pas trouvée. Vous devez utiliser <'4/1/2015'.
Curtis Yallop
Pensez également à utiliser le format de date international «2015-03-01». Au Canada (et dans de nombreux autres endroits), un format officiel est JJ / MM / AAAA, ce qui rend les deux formats ambigus et problématiques.
Curtis Yallop
Cette réponse ne traite pas de 2 tableaux, comme demandé dans la question.
Curtis Yallop
Oui je suis d'accord, mais je prouve juste une solution pas une solution internationale .. vous devez changer un certain ordre ...
pankaj