web-dev-qa-db-fra.com

Comparer DATETIME et DATE en ignorant la partie heure

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?

137
abatishchev

Utilisez CAST vers le nouveau type de données DATE dans SQL Server 2008 pour comparer uniquement la partie de date:

IF CAST(DateField1 AS DATE) = CAST(DateField2 AS DATE)
235
marc_s

La réponse de Marc présente un petit inconvénient, à savoir que les deux champs de date ont été convertis en typographie, ce qui signifie que vous ne pourrez pas tirer parti des index.

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

  • Le champ de date indexé (appelez-le DF1) ne doit pas être touché par aucun type de fonction.
  • Vous devez donc comparer DF1 à l’ensemble des valeurs datetime du jour de DF2.
  • Cela va de la partie date de DF2 à la date du lendemain de DF2.
  • C'est à dire. (DF1 >= CAST(DF2 AS DATE)) AND (DF1 < DATEADD(dd, 1, CAST(DF2 AS DATE)))
  • NOTE: Il est très important que la comparaison soit > = (égalité autorisée) à la date de DF2, et (strictement) < le lendemain de 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.

  • Cast la date comme un flotteur.
  • Tronquer la partie décimale
  • Remettre la valeur en date et heure
  • C'est à dire. CAST(FLOOR(CAST(DF2 AS FLOAT)) AS DATETIME)
59
Disillusioned

Bien que j'ai voté la réponse marquée comme correcte. Je voulais aborder quelques points pour quiconque tomberait dessus.

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

Notez que le formulaire '2007-02-12' est considéré comme indépendant des langues pour les types de données DATE, DATETIME2 et DATETIMEOFFSET.

Faire une comparaison de date en utilisant l'approche susmentionnée est simple. Considérons l'exemple suivant, artificiel.

--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, évitez toute manipulation de la colonne filtrée, car cela pourrait 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 le stocker sous la forme DATETIME avec minuit comme heure. Parce que:

Lorsque SQL Server convertit le littéral en type de colonne filtrée, il suppose minuit lorsqu'une heure n'est pas indiquée. Si vous souhaitez qu'un tel filtre renvoie toutes les lignes 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
4
pim

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
1
reza.cse08