2011-05-09 5 views
2

SQL Server 2005:SQL Server entre deux champs DateHeure, ne fonctionne pas correctement

La vue suivante

SELECT CONVERT(VARCHAR(20), keyedtimestamp, 101) as KeyedDate 
    FROM TMSSTATFILE_STATS a                 
    WHERE (CONVERT(VARCHAR(20), a.KeyedTimestamp, 101) BETWEEN '03/01/2011' And '03/31/2011') 
ORDER BY KeyedDate 

Les résultats sont donnés pour les dates clavetés 3/2/2011 à 3/31/2011.

Si je change la première date à 03/00/2011

SELECT CONVERT(VARCHAR(20), keyedtimestamp, 101) as KeyedDate 
    FROM TMSSTATFILE_STATS a                 
    WHERE (CONVERT(VARCHAR(20), a.KeyedTimestamp, 101) BETWEEN '03/00/2011' And '03/31/2011') 
ORDER BY KeyedDate 

donne maintenant des données pour les dates 3/1/2011 à 3/31/2011

Le champ KeyedTimestamp est DateTime et il y a des moments associés à ces enregistrements. Tous les enregistrements pour le 31/03/2011 sont comptabilisés. Je sais que je peux le faire en fournissant le maximum de temps à la deuxième date entre les deux, donc je ne cherche pas une alternative, mais plutôt une compréhension de pourquoi il ignore les enregistrements du premier, même s'il incorpore ceux à partir du 31

presque comme si son contrôle pour 3/1/2011 23:59:59, j'espérais pouvoir éliminer ce genre de contrôle où je me soucie seulement de la date, pas le temps

Répondre

7

Évitez une fonction sur la colonne en n'utilisant pas BETWEEN. Une fonction signifie un indice ne sera jamais utilisé

WHERE 
    a.KeyedTimestamp >= '20110301' AND a.KeyedTimestamp < '20110401' 

Et pre-SQL Server 2008 yyyymmdd est le seul format de date sûre.

+1

* Et le pré-SQL Server 2008 yyyymmdd est le seul format de date sûr. * ... Sauf si vous utilisez 'Set DateFormat'. – Thomas

+1

@Thomas: c'est pourquoi yyyymdd est sûr à utiliser: pas de dépendance sur Set DateFormat et il est indépendant de l'environnement. S'appuyant sur définir DateFormat ou définir la langue n'est pas sûr à mon humble avis. Que se passe-t-il s'il s'agit d'une application tierce qui doit s'exécuter sur les boîtes SQL du client? Avez-vous lu le dos et commenté avec marc_s dans mon lien? – gbn

+0

DateFormat devrait toujours fonctionner. En fait, je crois que les pilotes ADO.NET envoient Set DateFormat. Ce problème remonte à plusieurs versions. Je me souviens d'avoir lu un article de Kalen Delaney le jour de SQL 7.0 sur le même sujet. Si vous écrivez la requête, l'utilisation de YYYYMMDD est la plus sûre, mais il existe souvent une couche d'abstraction entre vous et la requête. – Thomas

2

Avez-vous essayé convertir en valeurs DATETIME (ou similaire), puis en comparant? Vous comparez les chaînes ... Je ne sais pas ce que '03/00/2011' signifie, conceptuellement, à l'opérateur BETWEEN. Franchement, je suis surpris que vos résultats aient du sens!

SQL Server 2008 a un type natif DATE, qui exclut les horodatages. Si vous ne disposez pas d'un type natif (vous avez mentionné V9) sans horodatage, vous pouvez utiliser quelque chose comme ceci:

SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, your_date_here)) 

Comme pris du blog de Anatoli Lubarsky:
http://blogs.x2line.com/al/archive/2006/02/17/1458.aspx

+0

Je suppose qu'en 2005, la connexion dit la version 9 mais je peux faire des CTE. 2005 n'a pas de date, seulement datetime. Je crois que la date n'est pas en jeu avant 2008, c'est pourquoi j'ai commencé la conversion drôle – Mohgeroth

+0

Bon, j'ai remarqué que vous avez mentionné V9 ... Néanmoins, vous ne devriez pas comparer les dates comme des chaînes ... c'est probablement l'échec ici . – Matthew

0

Datetime compare n'est pas entrer, tout est VARCHAR pendant que vous comparez.

Essayez:

SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, keyedtimestamp)) as KeyedDate 
FROM TMSSTATFILE_STATS a                 
WHERE DATEADD(dd, 0, DATEDIFF(dd, 0, keyedtimestamp)) BETWEEN '03/01/2011' AND '03/31/2011' 
ORDER BY DATEADD(dd, 0, DATEDIFF(dd, 0, keyedtimestamp)) 
+0

Cela fonctionne et est le comportement que j'étais à la recherche de. J'ai été surpris que ça fonctionne vu la conversion à varchar, donc je me demandais ce qui se passait dans les coulisses pour que ça marche en premier lieu. – Mohgeroth

3

Vous ne devriez pas être convertir les datetimes à cordes. Au lieu de cela, comparez-les en tant que datetimes. On dirait que vous essayez de contourner le problème des temps d'être stockées:

Select DateAdd(d, DateDiff(d, 0, T.KeyedTimeStamp), 0) As KeyedDate 
From TMSSTATFILE_STATS As T 
Where T.KeyedTimeStamp >= '20110301' 
    And T.KeyedTimeStamp < DateAdd(m,1,'20110301') 

Il convient de noter que DateTimeVal Between DateTimeA And DateTimeB se traduit DateTimeVal >= DateTimeA And DateTimeVal <= DateTimeB. C'est-à-dire qu'il inclut les deux points d'extrémité. Dans la solution ci-dessus, je reçois le premier jour du mois suivant et demande toutes les valeurs strictement inférieures à cette valeur, ce qui signifie que toutes les valeurs du mois de mars, y compris les heures, seront incluses. Enfin, l'instruction Select supprime la valeur temporelle de toutes les valeurs KeyedTimeStamp renvoyées.

Questions connexes