Sélectionnez l'instruction en utilisant Between with datetime type ne récupère pas tous les champs?

Je suis confronté à un résultat de requête étrange et je veux vous requestr pourquoi je suis confronté à ce problème.

Je stocke certaines données datetime dans TestTable comme suit:

creation_time ----------------------- 2010-07-10 00:01:43.000 2010-07-11 00:01:43.000 2010-07-12 00:01:43.000 

Cette table est créée et remplie comme suit:

 create table TestTable(creation_time datetime); Insert into TestTable values('2010-07-10 00:01:43.000'); Insert into TestTable values('2010-07-11 00:01:43.000'); Insert into TestTable values('2010-07-12 00:01:43.000'); 

quand j'exécute cette requête, j'obtiens deux rangées seulement au lieu de trois comme je m'y attendais:

 SELECT * FROM TestTable WHERE creation_time BETWEEN CONVERT(VARCHAR(10),'2010-07-10',111) -- remove time part and CONVERT(VARCHAR(10),'2010-07-12',111) -- remove time part 

Ou si j'exécute cette requête, le même problème ..

 SELECT * FROM TestTable WHERE CONVERT(datetime,creation_time,111) BETWEEN CONVERT(VARCHAR(10),'2010-07-10',111) -- remove time part and CONVERT(VARCHAR(10),'2010-07-12',111) -- remove time part 

Ma question :

  • Pourquoi la dernière rangée ('2010-07-12 00: 01: 43.000') n'apparaît pas dans le résultat, même si je fixe la plage de dates pour couvrir toute la journée du 2010-07-10 au 2010-07-12 ?
  • J'utilise Sql Server 2005 Express Edition avec Windows XP 32 bits.
  • J'essaie de ne pas utiliser une solution de contournement telle que l'augmentation de la plage de dates pour couvrir le jour supplémentaire pour get les jours que je veux.

Merci .

Vous devez également supprimer la partie time de creation_time. Utilisez simplement le même CONVERT si cela fonctionne.

Actuellement, vous requestz si le 2010-07-12 00: 01: 43.000 est inférieur au 2010-07-12 00: 00: 00.000, ce qui n'est pas vrai.

il n'affiche pas la date parce que vous avez supprimé la partie heure, ce qui rendrait la date équivalente à '2010-07-12 00:00:00.000' et puisque la dernière rangée est plus grande que celle-ci, elle n'est donc pas affichée dans le résultats de la requête.

Votre script devrait ressembler à ceci:

 SELECT * FROM TestTable WHERE creation_time BETWEEN convert(datetime, convert(char, '2010-07-10', 106))-- remove time part and **DATEADD**(day, 1, convert(datetime, convert(char, '2010-07-**11**', 106))) -- remove time part and add 1 day 

Ce script renverra tous entre 2010-07-10 00:00:00 et 2010-07-12 00:00:00. Fondamentalement, cela signifie tous les éléments créés en 2 jours: 2010-07-10 et 2010-07-11.

La conversion de colonnes dans votre table pour la comparaison peut être coûteuse et ne pas utiliser les index. Si vous avez un million de lignes dans votre table et que vous avez un index sur creation_time, vous allez effectuer une parsing d'index et convertir toutes les valeurs de million en une string pour comparaison.

Je trouve préférable d'utiliser> = la date de début et <(date de fin + 1 jour):

 SELECT * FROM TestTable WHERE creation_time >= '2010-07-10' AND creation_time < dateadd(day, 1, '2010-07-12') 

Et la raison pour laquelle votre second ne fonctionne pas est que le format 111 utilise des barres obliques ("2010/07/10"), le format 120 utilise des tirets ("2010-07-10"). Vos convertis ne font rien à vos dates de début et de fin parce que vous convertissez une string en varchar, pas une date. Si vous avez fait cela, cela pourrait fonctionner, mais je reorderais quand même de ne pas faire la conversion:

 SELECT * FROM TestTable WHERE CONVERT(datetime, creation_time, 111) BETWEEN CONVERT(VARCHAR(10), CONVERT(datetime, '2010-07-10'), 111) -- remove time part and CONVERT(VARCHAR(10), CONVERT(datetime, '2010-07-12'), 111) -- remove time part 

Date / heure comprise entre le 7/10/2010 et le 7/12/2010:

 SELECT * FROM TestTable WHERE creation_time BETWEEN CONVERT(VARCHAR,'2010-07-10',101) -- remove time part and CONVERT(VARCHAR,'2010-07-13',101) -- remove time part