web-dev-qa-db-fra.com

Comment puis-je tronquer une date/heure dans SQL Server?

Quel est le meilleur moyen de tronquer une valeur datetime (pour supprimer heures, minutes et 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
246
Julio César

Cela continue à rassembler 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 les versions ultérieures, rien de plus simple:

cast(getDate() As Date)

Notez que les trois derniers paragraphes près du bas s'appliquent toujours et vous devez souvent prendre du recul et trouver un moyen d'éviter le casting en premier lieu.

Mais il y a aussi d'autres moyens d'y parvenir. Voici les plus communs.

La bonne manière (nouvelle depuis Sql Server 2008):

cast(getdate() As Date)

La bonne façon (ancien):

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

C’est plus vieux maintenant, mais cela vaut la peine de le savoir car il peut également s’adapter facilement à d’autres moments, comme le premier moment du mois, la minute, l’heure ou l’année.

Cette méthode correcte utilise des fonctions documentées faisant partie du standard Ansi et dont le fonctionnement est garanti, mais cela peut être un peu plus lent. Cela fonctionne en trouvant combien de jours il y a du jour 0 au jour actuel et en ajoutant ce nombre de jours en arrière au jour 0. Cela fonctionnera quelle que soit la façon dont votre date/heure est stockée et quelles que soient vos paramètres régionaux.

Le moyen rapide:

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

Cela fonctionne car les colonnes datetime sont stockées sous forme de valeurs binaires de 8 octets. Lancez-les pour flotter, mettez-les au sol pour supprimer la fraction, et la partie temps des valeurs disparaîtra lorsque vous les renvoyerez à la date et à l'heure. C'est juste un décalage de bits sans logique compliquée et c'est très rapide. 

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

La mauvaise direction:

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

La mauvaise façon de procéder fonctionne en convertissant en chaîne, en tronquant la chaîne et en reconvertissant en date/heure. C'est faux, pour deux raisons: 1) cela pourrait ne pas fonctionner avec tous les paramètres régionaux et 2) il s'agit du moyen le plus lent possible de le faire ... et pas seulement un peu; c'est comme un ordre de grandeur ou deux fois plus lent que les autres options. 


Mise à jour Cela a eu quelques votes ces derniers temps, et je tiens donc à ajouter que depuis que je publie ça, j'ai vu des preuves assez solides que Sql Server optimisera la différence de performance entre la manière "correcte" et le "rapide" façon, ce qui signifie que vous devriez maintenant favoriser l'ancien.

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 endroits, la base de données est déjà votre goulot d'étranglement. C'est généralement le serveur qui coûte le plus cher pour ajouter du matériel pour améliorer les performances et le plus difficile pour obtenir ces ajouts (vous devez équilibrer les disques avec de la mémoire, par exemple). C'est aussi le plus difficile à faire évoluer vers l'extérieur, à la fois techniquement et d'un point de vue commercial; techniquement, il est beaucoup plus facile d'ajouter un serveur Web ou un serveur d'applications qu'un serveur de base de données et même si cela était faux, vous ne payez pas plus de 20 000 dollars par licence serveur pour IIS ou Apache. 

Ce que je veux dire, c'est que chaque fois que cela est possible, vous devriez effectuer ce travail au niveau de l'application. La uniquement heure à laquelle vous devriez jamais trouver vous-même tronquer une date/heure sur Sql Server est le moment où vous devez grouper à la journée, et même alors, vous devriez probablement avoir une colonne supplémentaire configurée comme une colonne calculée, maintenue à l'insertion/update time, ou maintenu dans la logique d'application. Obtenez ce travail cpu-lourd, révolutionnaire, de votre base de données.

443
Joel Coehoorn

Pour SQL Server 2008 uniquement

CAST(@SomeDateTime AS Date) 

Puis remettez-le à datetime si vous voulez

CAST(CAST(@SomeDateTime AS Date) As datetime)
44
DJ.

Juste pour une réponse plus complète, voici un moyen pratique de tronquer toutes les parties de la date et incluant les minutes (remplacez GETDATE() par la date à tronquer).

Ceci diffère de la réponse acceptée en ce que vous pouvez utiliser non seulement dd (jours), mais n’importe laquelle des parties de date (voir ici ):

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

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

20
Lucero

L'extrait que j'ai trouvé sur le Web quand je devais le faire était le suivant:

 dateadd(dd,0, datediff(dd,0, YOURDATE))
 e.g.
 dateadd(dd,0, datediff(dd,0, getDate()))
7
Tom Ritter
CONVERT(DATE, <yourdatetime>) or CONVERT(DATE, GetDate()) or CONVERT(DATE, CURRENT_TIMESTAMP)
1
Dean

En SQL 2005, votre fonction trunc_date pourrait être écrite comme ceci.

(1)

CREATE FUNCTION trunc_date(@date DATETIME)
RETURNS DATETIME
AS
BEGIN
    CAST(FLOOR( CAST( @date AS FLOAT ) )AS DATETIME)
END

La première méthode est beaucoup plus propre. Il utilise seulement 3 appels de méthode, y compris CAST () final, et n'effectue aucune concaténation de chaîne, ce qui est un plus automatique. De plus, il n’ya pas d’énormes moulages de caractères ici. Si vous pouvez imaginer que les horodatages Date/Heure puissent être représentés, la conversion de dates en chiffres et de dos en dates est un processus assez simple.

(2)

CREATE FUNCTION trunc_date(@date DATETIME)
RETURNS DATETIME
AS
BEGIN
      SELECT CONVERT(varchar, @date,112)
END

Si vous êtes préoccupé par l’implémentation par Microsoft de datetime (2) ou (3), cela pourrait aller.

(3)

CREATE FUNCTION trunc_date(@date DATETIME)
RETURNS DATETIME
AS
BEGIN
SELECT CAST((STR( YEAR( @date ) ) + '/' +STR( MONTH( @date ) ) + '/' +STR( DAY(@date ) )
) AS DATETIME
END

Troisièmement, la méthode la plus verbeuse. Cela nécessite de décomposer la date en ses parties année, mois et jour, de les assembler au format "aaaa/mm/jj", puis de les retranscrire en une date. Cette méthode implique 7 appels de méthode, y compris le dernier CAST (), sans parler de la concaténation de chaînes.

1
AlejandroR

vous pouvez simplement faire ceci (SQL 2008):

declare @SomeDate date = getdate ()

select @SomeDate

2009-05-28

0

sélectionnez Cast (Floor (cast (getdate () en tant que float)) que datetime) Référence: http://microsoftmiles.blogspot.com/2006/11/remove-time-from-datetime-in-sql -server.html

0
Sudhir Bastakoti

Oracle: 

TRUNC(SYSDATE, 'MONTH')

Serveur SQL: 

DATEADD(DAY, - DATEPART(DAY, DateField) + 1, DateField)

Peut être utilisé de la même manière pour tronquer des minutes ou des heures à partir d'une date.

0
Markus

Pour ceux d'entre vous qui sont venus ici à la recherche d'un moyen de tronquer un champ DATETIME en moins d'une journée, par exemple toutes les minutes, vous pouvez utiliser ceci:

SELECT CAST(FLOOR(CAST(GETDATE() AS FLOAT)) + (FLOOR((CAST(GETDATE() AS FLOAT) - FLOOR(CAST(GETDATE() AS FLOAT))) * 1440.0) + (3.0/86400000.0)) / 1440.0 AS DATETIME)

donc, si aujourd'hui était 2010-11-26 14:54:43.123, ceci renverrait 2010-11-26 14:54:00.000.

Pour modifier l'intervalle auquel il correspond, remplacez 1440.0 par le nombre d'intervalles d'un jour, par exemple:

24hrs          =   24.0  (for every hour)
24hrs / 0.5hrs =   48.0  (for every half hour)
24hrs / (1/60) = 1440.0  (for every minute)

(Mettez toujours un .0 à la fin pour transtyper implicitement un float.)


Pour ceux d'entre vous qui se demandent à quoi sert le (3.0/86400000) dans mon calcul, SQL Server 2005 ne semble pas transtyper de FLOAT à DATETIME avec précision, donc cela ajoute 3 millisecondes avant de le recouvrir.

0
BG100

Cette requête devrait vous donner un résultat équivalent à trunc(sysdate) dans Oracle.

SELECT  * 
FROM    your_table
WHERE   CONVERT(varchar(12), your_column_name, 101)
      = CONVERT(varchar(12), GETDATE(), 101)

J'espère que cela t'aides!

0
Sandeep Gaadhe

Vous pouvez également extraire date using Substring à partir de la variable datetime et revenir à datetime ignorera la partie heure.

declare @SomeDate datetime = '2009-05-28 16:30:22'
SELECT cast(substring(convert(varchar(12),@SomeDate,111),0,12) as Datetime) 

En outre, vous pouvez accéder à des parties de la variable datetime et les fusionner avec une date de construction tronquée, quelque chose comme ceci:

SELECT cast(DATENAME(year, @Somedate) + '-' + 
       Convert(varchar(2),DATEPART(month, @Somedate)) + '-' +
       DATENAME(day, @Somedate) 
       as datetime)
0
NeverHopeless