300 votes

Comment puis-je tronquer une date dans le serveur SQL ?

Quelle est la meilleure façon de tronquer une valeur de date (afin de supprimer les heures, les minutes et les secondes) dans SQL Server 2008 ?

Par exemple :

declare @SomeDate datetime = '2009-05-28 16:30:22'
select trunc_date(@SomeDate)

-----------------------
2009-05-28 00:00:00.000

533voto

Joel Coehoorn Points 190579

Il continue à recueillir fréquemment des votes supplémentaires, même plusieurs années plus tard, et je dois donc le mettre à jour pour les versions modernes de Sql Server. Pour Sql Server 2008 et plus, c'est simple :

cast(getDate() As Date)

Notez que les trois derniers paragraphes vers le bas sont toujours d'actualité et que vous devez souvent prendre du recul pour trouver un moyen d'éviter le plâtre en premier lieu.

Mais il existe aussi d'autres moyens d'y parvenir. Voici les plus courantes.

La méthode correcte (nouvelle depuis Sql Server 2008) :

cast(getdate() As Date)

La manière correcte (ancienne) :

dateadd(dd, datediff(dd,0, getDate()), 0)

Cette méthode est plus ancienne aujourd'hui, mais elle mérite d'être connue car elle peut facilement s'adapter à d'autres moments, comme le premier moment du mois, de la minute, de l'heure ou de l'année.

Cette méthode correcte utilise des fonctions documentées qui font partie de la norme ansi et dont le fonctionnement est garanti, mais elle peut être un peu plus lente. Elle fonctionne en trouvant combien de jours il y a entre le jour 0 et le jour actuel, et en ajoutant ce nombre de jours au jour 0. Elle fonctionnera quelle que soit la façon dont votre date est stockée et quelle que soit votre locale.

La méthode rapide :

cast(floor(cast(getdate() as float)) as datetime)

Cela fonctionne parce que les colonnes de date sont stockées sous forme de valeurs binaires de 8 octets. Transformez-les en valeurs flottantes, mettez-les au plancher pour supprimer la fraction, et la partie temps des valeurs disparaît lorsque vous les retransformez en date. Ce n'est qu'un simple décalage de bits, sans logique compliquée, et c'est très rapide.

Sachez que cela repose sur un détail d'implémentation que Microsoft est libre de modifier à tout moment, même dans une mise à jour de service automatique. Ce n'est pas non plus très portable. En pratique, il est très peu probable que cette implémentation change prochainement, mais il est tout de même important d'être conscient du danger si vous choisissez de l'utiliser. Et maintenant que nous avons la possibilité d'utiliser une date, c'est rarement nécessaire.

Le mauvais chemin :

cast(convert(char(11), getdate(), 113) as datetime)

La mauvaise méthode consiste à convertir en une chaîne de caractères, à tronquer cette chaîne et à la reconvertir en date. C'est mauvais pour deux raisons : 1) il se peut que cela ne fonctionne pas dans toutes les régions et 2) c'est la façon la plus lente possible de faire cela... et pas seulement un peu ; c'est un ordre de grandeur ou deux plus lent que les autres options.


Mise à jour Ce sujet a reçu quelques votes dernièrement, et je veux donc ajouter que depuis que j'ai posté ce message, j'ai vu des preuves assez solides que Sql Server optimisera la différence de performance entre la manière "correcte" et la manière "rapide", ce qui signifie que vous devriez maintenant favoriser la première.

Dans les deux cas, vous voulez Rédigez vos requêtes pour éviter d'avoir à le faire en premier lieu. . Il est très rare que vous deviez effectuer ce travail sur la base de données.

Dans la plupart des cas, la base de données est déjà votre goulot d'étranglement. C'est généralement le serveur auquel il est le plus coûteux d'ajouter du matériel pour améliorer les performances et le plus difficile à mettre en place (vous devez équilibrer les disques et la mémoire, par exemple). C'est aussi le plus difficile à faire évoluer, à la fois d'un point de vue technique et d'un point de vue commercial ; il est beaucoup plus facile techniquement d'ajouter un serveur web ou d'application qu'un serveur de base de données et même si c'était faux, vous ne payez pas plus de 20 000 $ par licence de serveur pour IIS ou Apache.

Ce que je veux dire, c'est que, dans la mesure du possible, vous devez effectuer ce travail au niveau de l'application. Le site uniquement La seule fois où vous devriez avoir à tronquer une date sur Sql Server est lorsque vous avez besoin de regrouper par jour, et même dans ce cas, vous devriez probablement avoir une colonne supplémentaire configurée comme une colonne calculée, maintenue au moment de l'insertion/mise à jour, ou maintenue dans la logique de l'application. Débarrassez votre base de données de ce travail lourd en termes d'index et de processeur.

0 votes

Joel, votre mise à jour de ce post est utile. Ce qui est étrange, c'est que j'ai trouvé que la méthode DateDiff était plus rapide, du moins en SQL 2008. Je vais essayer d'exécuter mes tests en SQL 2000 et je verrai si je peux poster une mise à jour.

6 votes

La "méthode rapide" est toujours la plus rapide pour sql 2008 selon un benchmark que je viens d'effectuer.

3 votes

FYI : stackoverflow.com/q/1177449/27535 y stackoverflow.com/q/133081/27535 Le dateadd/datediff "gagne...". Pour une seule variable, on s'en fiche bien sûr, et on espère que vous avez calculé des colonnes ou autres sur un million de lignes :-)

45voto

DJ. Points 10596

Pour SQL Server 2008 uniquement

CAST(@SomeDateTime AS Date) 

Puis, si vous le souhaitez, vous pouvez le convertir en datetime.

CAST(CAST(@SomeDateTime AS Date) As datetime)

0 votes

Bon point : je suis encore en 2005 et donc, pour 2008, c'est probablement la nouvelle méthode "correcte" et elle pourrait même égaler les performances de la méthode "rapide".

1 votes

Les performances de cette nouvelle méthode sont encore plus rapides que celles de la méthode "rapide".

23voto

Lucero Points 38928

Dans le but d'obtenir une réponse plus complète, voici un moyen efficace de tronquer n'importe quelle partie de la date jusqu'aux minutes incluses (remplacez GETDATE() avec la date à tronquer).

Cette réponse est différente de la réponse acceptée dans la mesure où vous pouvez utiliser non seulement dd (jours), mais n'importe laquelle des parties de la date (voir aquí ) :

dateadd(minute, datediff(minute, 0, GETDATE()), 0)

Notez que dans l'expression ci-dessus, le 0 est une date constante au début d'une année (1900-01-01). Si vous avez besoin de tronquer à des parties plus petites, comme des secondes ou des millisecondes, vous devez prendre une date constante qui est plus proche de la date à tronquer pour éviter un débordement.

1 votes

C'était monstrueusement utile. J'ai cherché partout un moyen de tronquer la date et l'heure à un endroit inférieur au jour complet.

1 votes

@Michael, merci pour le feedback, c'est bon de savoir que ça vous a aidé !

1 votes

+1 ceci devrait avoir plus de upvotes, c'est une excellente réponse qui développe la réponse choisie.

7voto

Tom Ritter Points 44352

L'extrait que j'ai trouvé sur le web lorsque j'ai dû faire cela était le suivant :

 dateadd(dd,0, datediff(dd,0, YOURDATE))
 e.g.
 dateadd(dd,0, datediff(dd,0, getDate()))

0 votes

Je suis sur 2005, mais je pensais que 2008 avait une nouvelle fonction pour cela ???

2 votes

Neat ! J'aurais eu recours à la séparation des parties de la date et à la manipulation des chaînes de caractères pour les reconstituer. Cela n'a peut-être rien à voir, mais SQL2008 possède un type de données de type date uniquement, sans élément temporel.

1 votes

Et notez que vous avez mélangé les opérandes de DateAdd, il s'agit de DateAdd(dd, DateDiff(...), 0) . Cela peut vous mordre si vous ne faites pas attention.

1voto

AlexKuznetsov Points 9555

Et vous pouvez réutiliser votre code sans perdre en performance si vous l'enveloppez comme un UDF en ligne :

http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/05/23/reuse-your-code-with-cross-apply.aspx

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X