Quelle méthode offre les meilleures performances lors de la suppression de la partie temps d'un champ datetime dans SQL Server?
a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)
ou
b) select cast(convert(char(11), getdate(), 113) as datetime)
La deuxième méthode envoie quelques octets de plus dans les deux cas, mais cela pourrait ne pas être aussi important que la vitesse de la conversion.
Les deux semblent également être très rapides, mais il peut y avoir une différence de vitesse lors du traitement de centaines de milliers ou plus de lignes?
En outre, est-il possible qu'il existe des méthodes encore meilleures pour se débarrasser de la partie temporelle d'un datetime dans SQL?
Réponses:
Strictement, la méthode
a
est la moins gourmande en ressources:Éprouvé moins gourmand en ressources processeur pour la même durée totale d'un million de lignes par quelqu'un avec beaucoup trop de temps à disposition: le moyen le plus efficace dans SQL Server pour obtenir la date à partir de la date + heure?
J'ai vu un test similaire ailleurs avec des résultats similaires aussi.
Je préfère le DATEADD / DATEDIFF car:
Exemple: Pourquoi mon expression CASE est-elle non déterministe?
Edit, oct 2011
Pour SQL Server 2008+, vous pouvez CAST vers
date
ieCAST(getdate() AS date)
. Ou utilisez simplement ledate
type de données afin de ne pas le supprimer.Edit, janv 2012
Un exemple concret de la flexibilité de ceci: besoin de calculer par heure ou date arrondie dans le serveur SQL
Edit, mai 2012
N'utilisez pas cela dans les clauses WHERE et similaires sans réfléchir: l'ajout d'une fonction ou CAST à une colonne invalide l'utilisation de l'index. Voir le numéro 2 ici: http://www.simple-talk.com/sql/t-sql-programming/ten-common-sql-programming-mistakes/
Maintenant, cela a un exemple de versions ultérieures de l'optimiseur SQL Server gérant correctement CAST à ce jour, mais généralement ce sera une mauvaise idée ...
Edit, sept. 2018, pour datetime2
la source
DATE
heure des données est odieusement restrictive quant à ce qu'elle vous permettra de faire en ce qui concerne des choses comme dateadd, dateiff et l'interaction avec d'autres types de données date / heure. Pour ces cas, l'DATEADD()
approche règne en maître.0218
lieu de2018
l'année et laDATEDIFF
partie de votre déclaration lève une exceptionThe conversion of a datetime2 data type to a datetime data type resulted in an out-of-range datetime value
Essayez:select DATEDIFF(dd, 0, convert(datetime2(0), '0218-09-12', 120))
SELECT DATEDIFF(dd, '19000101', convert(datetime2(0), '0218-09-12', 120))
Dans SQL Server 2008, vous pouvez utiliser:
la source
datetime
en adate
, et donc votre solution se résume effectivement à justeCONVERT(DATE,getdate())
, ce qui a déjà été suggéré plus d'une fois.CAST(GETDATE() AS DATE)
ou strictement ANSICAST(CURRENT_TIMESTAMP AS DATE)
qui, je pense, ne vaut rien. Restez avec le premier.Bien sûr, c'est un vieux fil mais pour le compléter.
À partir de SQL 2008, vous pouvez utiliser le type de données DATE pour effectuer simplement:
la source
... n'est pas une bonne solution, selon les commentaires ci-dessous.
Je supprimerais cette réponse, mais je la laisserai ici comme contre-exemple car je pense que l'explication des commentateurs de pourquoi ce n'est pas une bonne idée est toujours utile.
la source
Dans SQL Server 2008, il existe un type de données DATE (également un type de données TIME).
ou
la source
Voici encore une autre réponse, à partir d'une autre question en double:
Cette méthode de nombre magique fonctionne légèrement plus rapidement que la méthode DATEADD. (Il ressemble à ~ 10%)
Le temps CPU sur plusieurs tours d'un million d'enregistrements:
Mais notez que ces chiffres ne sont peut-être pas pertinents car ils sont déjà TRÈS rapides. À moins d'avoir des jeux d'enregistrements de 100 000 ou plus, je ne pouvais même pas obtenir le temps CPU pour lire au-dessus de zéro.
Compte tenu du fait que DateAdd est destiné à cet effet et est plus robuste, je dirais utiliser DateAdd.
la source
'12:00:00.003'
ce que je pense est beaucoup mieux, cependant.la source
J'aime vraiment:
Le
120
code de format contraindra la date dans la norme ISO 8601:Super facile à utiliser dans dplyr (
R
) et pandas (Python
)!la source
IL FAUT SE MÉFIER!
Les méthodes a) et b) n'ont PAS toujours la même sortie!
Production:
2014-01-01 00:00:00.000
Production:
2013-12-31 00:00:00.000
(Testé sur MS SQL Server 2005 et 2008 R2)
EDIT: Selon le commentaire d'Adam, cela ne peut pas se produire si vous lisez la valeur de date dans le tableau, mais cela peut se produire si vous fournissez votre valeur de date comme un littéral (exemple: comme paramètre d'une procédure stockée appelée via ADO.NET).
la source
DATETIME
colonne. Le plus haut disponible est .997 De: msdn.microsoft.com/en-us/library/ms187819.aspx vous verrez que les valeurs sont arrondies pour avoir la millième place à 0, 3 ou 7. L'OP ne verra pas la valeur de votre test dans leurs tableaux.Temps de bande sur les insertions / mises à jour en premier lieu. En ce qui concerne la conversion à la volée, rien ne peut battre une fonction définie par l'utilisateur en termes de maintenabilité:
L'implémentation de
date_only
peut être tout ce que vous aimez - maintenant, elle est abstraite et le code d'appel est beaucoup plus propre.la source
WHERE DateAdd(DateDiff(Column)) = @DateValue
n'utilisera pas d'index. D'un autre côté,WHERE Column >= dbo.UDF(@DateValue) AND Column < dbo.UDF(@DateValue + 1)
est SARGable. Alors faites attention à la façon dont vous le dites.Voir cette question:
Comment puis-je tronquer un datetime dans SQL Server?
Quoi que vous fassiez, n'utilisez pas la méthode chaîne . C'est à peu près la pire façon de le faire.
la source
Déjà répondu, mais mal jeté cela aussi ... cela semble aussi bien préformer mais cela fonctionne en jetant la décimale (qui stocke le temps) du flotteur et en ne retournant qu'une partie entière (qui est la date)
la deuxième fois que j'ai trouvé cette solution ... j'ai saisi ce code
la source
Cette méthode n'utilise pas de fonction de chaîne.
Date
est fondamentalement un vrai type de données avec des chiffres avant que les décimales ne soient une fraction de jour.je suppose que ce sera plus rapide que beaucoup.
la source
Pour moi, le code ci-dessous est toujours gagnant:
la source
sélectionnez CONVERTIR (char (10), GetDate (), 126)
la source
je pense que vous voulez dire
cast(floor(cast(getdate()as float))as datetime)
réel n'est que de 32 bits et pourrait perdre des informations
C'est le plus rapide
cast(cast(getdate()+x-0.5 as int)as datetime)
... mais seulement 10% plus rapide
(about 0.49 microseconds CPU vs. 0.58)
Cela a été recommandé et prend le même temps dans mon test tout à l'heure:
DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)
Dans SQL 2008, la fonction SQL CLR est environ 5 fois plus rapide que l'utilisation d'une fonction SQL, soit 1,35 microsecondes contre 6,5 microsections, ce qui indique une surcharge d'appel de fonction beaucoup plus faible pour une fonction SQL CLR par rapport à un simple UDF SQL.
Dans SQL 2005, la fonction SQL CLR est 16 fois plus rapide, selon mes tests, par rapport à cette fonction lente:
la source
Et alors
select cast(cast my_datetime_field as date) as datetime)
? Cela se traduit par la même date, avec l'heure définie à 00:00, mais évite toute conversion en texte et évite également tout arrondi numérique explicite.la source
Je pense que si vous vous en tenez strictement à
TSQL
cela, c'est le moyen le plus rapide de tronquer le temps:J'ai trouvé que cette méthode de troncature était environ 5% plus rapide que la
DateAdd
méthode. Et cela peut être facilement modifié pour arrondir au jour le plus proche comme ceci:la source
Ici, j'ai créé une fonction pour supprimer certaines parties d'un datetime pour SQL Server. Usage:
create function dbo.uf_RoundDateTime(@dt as datetime, @part as char) returns datetime as begin if CHARINDEX( @part, 'smhd',0) = 0 return @dt; return cast( Case @part when 's' then convert(varchar(19), @dt, 126) when 'm' then convert(varchar(17), @dt, 126) + '00' when 'h' then convert(varchar(14), @dt, 126) + '00:00' when 'd' then convert(varchar(14), @dt, 112) end as datetime ) end
la source
Juste au cas où quelqu'un chercherait ici une version Sybase car plusieurs des versions ci-dessus ne fonctionnaient pas
la source
cast
: Pour SQL Server 2008+, vous pouvez CAST à ce jour. Ou utilisez simplement la date pour ne pas perdre de temps.datetime
endate
: aucun de ceux-ci n'a un format inhérent.Si possible, pour des choses spéciales comme celle-ci, j'aime utiliser les fonctions CLR.
Dans ce cas:
la source
Personnellement, j'utilise presque toujours des fonctions définies par l'utilisateur dans le cas de SQL Server 2005 (ou version inférieure), cependant, il convient de noter qu'il existe des inconvénients spécifiques à l'utilisation des FDU, en particulier si vous les appliquez aux clauses WHERE (voir ci-dessous et commentaires sur cette réponse pour plus de détails). Si vous utilisez SQL Server 2008 (ou supérieur) - voir ci-dessous.
En fait, pour la plupart des bases de données que je crée, j'ajoute ces UDF juste au début car je sais qu'il y a 99% de chances que j'en ai besoin tôt ou tard.
J'en crée un pour "date seulement" et "heure seulement" (bien que celui "date seulement" soit de loin le plus utilisé des deux).
Voici quelques liens vers une variété d'UDF liés à la date:
Fonctions essentielles de date, d'heure et de date et heure de SQL Server Fonction
Get Date Only
Ce dernier lien montre pas moins de 3 façons différentes d'obtenir la date seulement une partie d'un champ datetime et mentionne certains avantages et inconvénients de chaque approche.
Si vous utilisez un UDF, il convient de noter que vous devez essayer d'éviter d'utiliser l'UDF dans le cadre d'une clause WHERE dans une requête, car cela entravera considérablement les performances de la requête. La raison principale en est que l'utilisation d'une FDU dans une clause WHERE rend cette clause non-sargable , ce qui signifie que SQL Server ne peut plus utiliser d'index avec cette clause afin d'améliorer la vitesse d'exécution des requêtes. En référence à ma propre utilisation des UDF, j'utiliserai fréquemment la colonne de date "brute" dans la clause WHERE, mais j'appliquerai l'UDF à la colonne SELECTed. De cette façon, l'UDF est uniquement appliqué à l'ensemble de résultats filtré et non à chaque ligne du tableau dans le cadre du filtre.
Bien sûr, la meilleure approche absolue pour cela consiste à utiliser SQL Server 2008 (ou supérieur) et à séparer vos dates et heures , car le moteur de base de données SQL Server fournit alors nativement les composants individuels de date et d'heure, et peut les interroger efficacement indépendamment sans avoir besoin d'un UDF ou d'un autre mécanisme pour extraire la partie date ou heure d'un type composite datetime.
la source
WHERE DateColumn >= {TimeTruncatingExpression}(@DateValue) AND DateColumn < {TimeTruncatingExpression}(@DateValue + 1)
. Je me sentais comme si je devais dire quelque chose puisque vous avez dit "J'utilise presque toujours des FDU" n'a expliqué aucun des inconvénients, ni la façon de faire une requête SARGable de date seulement.J'utiliserais:
Ainsi, vous créez efficacement un nouveau champ à partir du champ de date que vous avez déjà.
la source
datetime
datetime
est préférable d' valeur, de les convertir en chaînes, de les concaténer ensemble et enfin de reconvertir le résultat qu'en effectuant par exemple des calculs directs sur l'originaldatetime
(la méthodeDATEADD
/DATEDIFF
)?MM
etDD
? Il n'y a pas de telles fonctions dans SQL Server.