web-dev-qa-db-fra.com

Quelle est la façon optimale de comparer les dates dans Microsoft SQL Server?

J'ai un champ SQL datetime dans une très grande table. Il est indexé et doit être interrogé.

Le problème est que SQL stocke toujours le composant d'heure (même s'il est toujours minuit), mais les recherches sont au jour plutôt qu'à l'heure.

declare @dateVar datetime = '2013-03-11;

select t.[DateColumn]
from MyTable t
where t.[DateColumn] = dateVar;

Ne retournera rien, car le t.[DateColumn] inclut toujours une composante temporelle.

Ma question est quelle est la meilleure façon de contourner cela?

Il semble y avoir deux principaux groupes d'options:

  1. Créez une deuxième variable à l'aide de dateadd et utilisez un between ... and ou >= ... and ... <=.

  2. Convertissez le t.[DateColumn] dans un composant de date uniquement - je pense que cela entraînera l'ignorance de tout index.

Les deux semblent très compliqués - je ne veux pas vraiment faire de comparaison de plage ou scanner la table.

Y a-t-il une meilleure façon?

Si l'une de ces options est toujours optimale, comment et pourquoi?

28
Keith

La conversion en DATE ou l'utilisation d'une plage de dates ouverte dans tous les cas donnera les meilleures performances. Pour info, les conversions à ce jour à l'aide d'un indice sont les plus performantes. Plus de tests sur différentes techniques dans l'article: Quel est le moyen le plus efficace pour couper le temps à partir de datetime? Publié par Aaron Bertrand

De cet article:

DECLARE @dateVar datetime = '19700204';

-- Quickest when there is an index on t.[DateColumn], 
-- because CONVERT can still use the index.
SELECT t.[DateColumn]
FROM MyTable t
WHERE = CONVERT(DATE, t.[DateColumn]) = CONVERT(DATE, @dateVar);

-- Quicker when there is no index on t.[DateColumn]
DECLARE @dateEnd datetime = DATEADD(DAY, 1, @dateVar);
SELECT t.[DateColumn] 
FROM MyTable t
WHERE t.[DateColumn] >= @dateVar AND 
      t.[DateColumn] < @dateEnd;

Toujours à partir de cet article: l'utilisation de BETWEEN, DATEDIFF ou CONVERT(CHAR(8)... est plus lente.

29

Voici un exemple:

J'ai une table Order avec un champ DateTime appelé OrderDate. Je souhaite récupérer toutes les commandes dont la date de commande est égale au 01/01/2006. il y a de nouvelles façons de le faire:

1) WHERE DateDiff(dd, OrderDate, '01/01/2006') = 0
2) WHERE Convert(varchar(20), OrderDate, 101) = '01/01/2006'
3) WHERE Year(OrderDate) = 2006 AND Month(OrderDate) = 1 and Day(OrderDate)=1
4) WHERE OrderDate LIKE '01/01/2006%'
5) WHERE OrderDate >= '01/01/2006'  AND OrderDate < '01/02/2006'

Est trouvé ici

11
paraselena

Obtenez des éléments lorsque la date se situe entre la date du et la date.

où convertir (date, fromdate, 103) <= '2016-07-26' et convertir (date, toDate, 103)> = '2016-07-26'

0
gaze

Vous pouvez ajouter une colonne calculée qui inclut uniquement la date sans l'heure. Entre les deux options, j'irais avec l'opérateur BETWEEN parce qu'il est plus "propre" pour moi et devrait mieux utiliser les index. La comparaison des plans d'exécution semble indiquer que BETWEEN serait plus rapide; cependant, dans les tests réels, ils ont effectué la même chose.

0
Michael L.