Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

SQL Server : Conserver la date ou l’heure d’un datetime (Comparaison des méthodes)

Les types dates de SQL Server, comportent toujours la date et l'heure alors que souvent nous ne souhaitons utiliser que l'un ou l'autre. Dans ce genre de situation nous « resetons » manuellement l'un ou l'autre partie qui ne intéresse pas.

Tout d'abord comment ne conserver que la partie date, cette liste et non limitative, et vous pourrez peut être trouver mieux en terme de perf.

SELECT CONVERT(datetime, CONVERT(char(10), X, 103), 103) FROM DateTable -- 18.5 sec
SELECT DATEADD(d, 0, FLOOR(CAST(X as float))) FROM DateTable -- 7.5 sec
SELECT CAST(FLOOR(CAST(X as float)) as datetime) FROM DateTable -- 6.3 sec
SELECT CAST(CAST(CAST(X as float) as int) as datetime) FROM DateTable -- 4.5 sec

-- Les conversions qui suivent ne fonctionnent pas à cause de l'arrondi
SELECT DATEADD(d, 0, CAST(X as int)) FROM DateTable -- 4.9 sec
SELECT CAST(CAST(X as int) as datetime) FROM DateTable -- 4.0 sec

X représente le champ date à convertir, DateTable contient environ 19 millions de dates (date et heure) pour effectuer les tests. Le temps indiqué derrière correspond au temps CPU approximatif consommé par la requête (sur ma machine).

La première méthode est la plus lente, elle repose sur CONVERT qui permet contrairement à CAST de passer le format souhaité de date. On a choisit le format 103 qui correspond à JJ/MM/AAAA c'est-à-dire le format utilisé en France. Ce format n'indique pas l'heure et qui permet en effectuant 2 CONVERT successif d'obtenir uniquement la date avec l'heure à minuit.

La seconde repose sur une conversion de date en float, un arrondit du float et une reconversion en datetime. Le gain est très net par rapports aux fonctions de date utilisé pour le premier exemple. Cette méthode je l'ai découverte grâce à Nix, ici.

Partons de cette méthode pour aller plus vite. Clairement l'arrondi du float est en trop, on peut réaliser la conversion directement en int. Quant au DATEADD il ne fait qu'une reconversion du int en datetime donc autant refaire un CAST en datetime à la place. Le problème comme l'a fait remarquer Nicolas en commentaire c'est que ces méthodes revoient un résultat faux à cause de l'arrondi produit par le CAST datetime vers int. Avec le DATEADD remplacé par un CAST on gagne une seconde de temps CPU. Et le FLOOR est remplacé par un CAST, le CAST d'un float vers int effectue une troncation des décimales, ce qui est l'effet souhaité chez nous.

Il n'y a pas de différence de performance entre l'utilisation du CONVERT ou du CAST, je préfère le CAST celui-ci étant un standard SQL. Le comportement de toutes les méthodes citées plus haut est identique pour un datetime et smalldatetime.

Maintenant pour conserver la composante heure d'un datetime.

SELECT CONVERT(datetime, CONVERT(char(10), X, 114), 114) FROM DateTable – 18.9 sec
SELECT CAST(CAST(X as binary(4)) as datetime) FROM DateTable – 5.7 sec

La première est la copie conforme de la première utilisée pour la partie date, elle d'ailleurs tout aussi rapide :o>

La seconde méthode convertit la date en binary(4) ce qui a pour effet de tronquer la partie date pour un datetime. Pour un smalldatetime il faudra convertir en binary(2) pour obtenir le même effet.

Si vous trouvez mieux et plus rapide postez un commentaire sur cette page. Merci :o)

Bon dev…

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :
Publié dimanche 29 avril 2007 10:00 par christian
Classé sous : ,

Commentaires

dimanche 29 avril 2007 11:24 by nletullier

# re: SQL Server : Conserver la date ou l’heure d’un datetime (Comparaison des méthodes)

Bonjour,

Intéressant, mais je noterais un "petit", voire un gros souci dans ces solutions. En effet, le CAST(ChampDate AS INT) ne fait pas une troncature de la partie décimale, mais un arrondi. Ce qui fait que toutes les solutions proposées qui utilisent un CAST en INT ne sont bonnes que pour les heures avant midi.

La solution consiste à faire, non pas un CAST en INT, mais le FLOOR d'un CAST en FLOAT.

Démonstration :

SET STATISTICS TIME ON

DECLARE @ladate DATETIME

SELECT @ladate = CONVERT(datetime, '03/16/2006 13:01')

SELECT @ladate,

CAST(FLOOR(CAST(@ladate AS float))  AS datetime) AS CastEnFloat,

DATEADD(d, 0, CAST(@ladate  as int)) AS DateAddSurCastEnInt,

CAST(CAST(@ladate AS int) AS datetime) CastEnInt,

CONVERT(datetime, CONVERT(char(10), @ladate, 103), 103) AS DoubleConvert

Nicolas.

dimanche 29 avril 2007 12:52 by christian

# re: SQL Server : Conserver la date ou l’heure d’un datetime (Comparaison des méthodes)

Merci d'avoir remarqué la boulette :o)

lundi 30 avril 2007 21:32 by Nix

# re: SQL Server : Conserver la date ou l’heure d’un datetime (Comparaison des méthodes)

Pourtant j'avais bien mi "float" dans mon exemple :p

http://www.sqlfr.com/codes/FAIRE-COUNT-GROUPER-DATE-AVEC-METHODE-FLOOR_42441.aspx

Hein christian Wink

jeudi 25 octobre 2007 11:33 by john

# re: SQL Server : Conserver la date ou l’heure d’un datetime (Comparaison des méthodes)

Bonjour,

J'ai trouvé cet article très intéressant, et je m'en suis servi pour optimisé des requêtes qui tronquaient l'heure en convertissant en chaines...

J'aimerais ajouter ma pierre à l'édifice.

Voici une autre méthode pour garder que la date, légèrement moins rapide :

SELECT cast(datediff(day,0,X) as datetime) FROM DateTable -- 3235 ms

en comparaison la méthode la plus rapide donne :

SELECT cast(cast(cast(X as float) as int) as datetime) FROM DateTable -- 3125 ms

Après par contre j'ai trouvé 2 autres méthodes plus rapide pour garder que l'heure :

SELECT X-datediff(day, 0, X) FROM DateTable -- 3448 ms

SELECT X-cast(cast(X as float) as int) FROM DateTable -- 3339 ms

l'autre méthode donnait :

SELECT cast(cast(X as binary(4)) as datetime) FROM DateTable -- 3732 ms

Le gros avantage, est qu'il n'est plus nécessaire de faire attention au type de donnée source.

Cela marche aussi bien pour les datetime que pour les smalldatetime.

PS : pour mes calculs de durées, j'ai travaillé sur une base sous SQL server 2000, sur une table avec 3 millions d'enregistrements.

Et j'ai demandé un min, pour que tout soit calculé, mais qu'il n'y ai pas de temps perdu à me renvoyer des millions de lignes.

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- La suite ...Proposition de collaboration rédactionnelle entre les communautés de développeurs et Microsoft France par LucasR le il y a 9 heures et 20 minutes

- [Fun] Votre simulateur de vol avec Microsoft ESP par Julien Chable le il y a 15 heures et 3 minutes

- [Best Practices] Customisation du My Site : Comment le modifier en amont et en aval par The Mit's Blog le il y a 16 heures et 17 minutes

- Patrick Tisseghem s'en est allé ... par The Mit's Blog le il y a 17 heures et 1 minutes

- MS AutoCollage par alex# le il y a 17 heures et 46 minutes

- Un grand SharePointeur nous a quitte : Patrick Tisseghem manquera à la communauté ! par RedoBlog - The .NET Gentleman !!! le il y a 18 heures et 12 minutes

- [WPF] Comment charger dynamiquement un fichier XAML qui définit des eventhandler ? par Thomas Lebrun le 09-04-2008, 10:56

- Article sur le filtrage des modèles de site SharePoint par The Grib's Lair [Sébastien PICAMELOT - MVP SharePoint] le 09-04-2008, 00:11

- Adopter votre Redo en 3D - Clone Virtuel - avec photosynth par RedoBlog - The .NET Gentleman !!! le 09-04-2008, 00:07

- [Expression Web] Astuce de la Semaine : Mettre en bouton ses macros dans une barre d'outils. par Expression Web & Me le 09-03-2008, 20:48