Meilleure approche pour supprimer la partie temps de datetime dans SQL Server

514

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?

Stephen Perelson
la source
1
J'ai essayé cela sur un million d'enregistrements dans l'une de mes tables de production et je n'ai pas pu obtenir une lecture précise des performances de toute façon. Les deux méthodes ont cependant renvoyé exactement la même quantité de données.
Stephen Perelson
9
Sur 18 000 000 lignes, voici ce que j'ai trouvé (SQL Server 2008): la méthode b est environ 24% plus lente que la méthode a. CAST (FLOOR (CAST (getdate () AS FLOAT)) AS DATETIME) est 3,5% plus lent que la méthode a. La méthode a semble être gagnante en ce qui concerne les performances. Merci à tous pour les bonnes réponses.
Stephen Perelson
46
Pourquoi diable SQL n'a-t-il pas de fonction intégrée pour le faire de toute façon? !!
Gary McGill
10
Le nouveau type de données DATE de SQL 2008 s'en chargera.
Philip Kelley

Réponses:

558

Strictement, la méthode aest la moins gourmande en ressources:

a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)

É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:

Edit, oct 2011

Pour SQL Server 2008+, vous pouvez CAST vers dateie CAST(getdate() AS date). Ou utilisez simplement le datetype 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

DECLARE @datetime2value datetime2 = '02180912 11:45' --this is deliberately within datetime2, year 0218
DECLARE @datetime2epoch datetime2 = '19000101'

select DATEADD(dd, DATEDIFF(dd, @datetime2epoch, @datetime2value), @datetime2epoch)
gbn
la source
3
@David Sopko pour l'édition d'octobre 2011 alors le code serait: sélectionnez le casting (GETDATE () comme date)
Choco Smith
1
Pour les versions plus récentes de SQL, l'utilisation de la date au lieu de datetime évite d'avoir à gérer des heures. Utilisez l'exemple suivant: declare noTime date = getdate (), withTime datetime = getdate () select @ noTime, @ withTime
ozkary
1
la distribution en tant que date est idéale si vous avez juste besoin de la date. Cependant, vous avez souvent besoin de la date actuelle à minuit pour pouvoir ensuite manipuler la date. l' DATEheure 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.
Xedni
Cela ne fonctionne pas pour chaque date. J'étais entré par erreur au 0218lieu de 2018l'année et la DATEDIFFpartie de votre déclaration lève une exception The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range datetime valueEssayez:select DATEDIFF(dd, 0, convert(datetime2(0), '0218-09-12', 120))
Bernhard Döbler
1
@ BernhardDöbler en juillet 2009, quand j'ai répondu, "0218" aurait été une date valide, donc vous ne seriez pas allé aussi loin. De plus, le "0" ne se convertit pas en 19000101 pour datetime2. Essayez cette sélectionSELECT DATEDIFF(dd, '19000101', convert(datetime2(0), '0218-09-12', 120))
gbn
69

Dans SQL Server 2008, vous pouvez utiliser:

CONVERT(DATE, getdate(), 101)
Anto Raja Prakash
la source
13
Le troisième argument n'a absolument aucune incidence sur le résultat lors de la conversion de a datetimeen a date, et donc votre solution se résume effectivement à juste CONVERT(DATE,getdate()), ce qui a déjà été suggéré plus d'une fois.
Andriy M
Utilisez simplement CAST(GETDATE() AS DATE)ou strictement ANSI CAST(CURRENT_TIMESTAMP AS DATE)qui, je pense, ne vaut rien. Restez avec le premier.
Ivanzinho
52

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:

SELECT CONVERT(DATE,GETDATE())
Arjan Fraaij
la source
21
SELECT CAST(FLOOR(CAST(getdate() AS FLOAT)) AS DATETIME)

... 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.

Gary McGill
la source
Voir la réponse de GBN, beaucoup ont enquêté sur cela. Les DATETIME ne sont PAS stockés sous forme de flottants, et donc l'utilisation de DATEADD / DATEDIFF évite la manipulation mathématique nécessaire pour CAST entre les types.
MatBailie
Je peux accepter que vous souhaitiez éviter une conversion de DATETIME en FLOAT pour la raison que vous décrivez, mais dans ce cas, la conversion implicite de zéro dans l'option OP (a) n'est-elle pas également un problème? Hmmm ... Je suppose que dans ce cas, ce n'est pas un FLOTTEUR et que le serveur est probablement assez intelligent pour supprimer les informations de temps. OK, je concède :-)
Gary McGill
Le 0 est en effet une conversion implicite d'un type numérique (INT je suppose) en DATETIME. Puisqu'il s'agit d'une expression constante, l'optimiseur peut le faire au moment de la compilation pour les procédures stockées et n'a besoin de le faire qu'une seule fois pour exécuter SQL de manière dynamique. En bref, il y a une surcharge unique pour cela, la requête basée sur FLOAT a la surcharge équivalente pour chaque ligne.
MatBailie
Lancer pour flotter est terriblement imprécis. Cette réponse doit être supprimée. Personne ne devrait utiliser ce code.
usr
3
Sans oublier qu'il n'est pas sûr de lancer pour flotter et revenir à datetime - float n'a pas assez de précision. Par conséquent, je pense que cela ne peut pas être recommandé du tout. Voir cet article pour plus de détails .
ErikE
17

Dans SQL Server 2008, il existe un type de données DATE (également un type de données TIME).

CAST(GetDate() as DATE)

ou

declare @Dt as DATE = GetDate()
Métaphore
la source
C'est ce que j'ai utilisé et cela a bien fonctionné. Semble comme la réponse la plus simple. Avez-vous des inconvénients à utiliser conjointement avec CONVERT?
joelmdev
1
CAST et CONVERT ont une fonction équivalente. La différence est que CAST fait partie de la norme ANSI, tandis que CONVERT est spécifique à T-SQL. Alors, utilisez CAST dans la mesure du possible.
troy
@troy J'utilise CAST parce que je peux enregistrer 3 lettres et la syntaxe est plus claire que CONVERT, la partie standard ANSI ne vaut rien
Ivanzinho
8

Voici encore une autre réponse, à partir d'une autre question en double:

SELECT CAST(CAST(getutcdate() - 0.50000004 AS int) AS datetime) 

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:

DATEADD   MAGIC FLOAT
500       453
453       360
375       375
406       360

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.

Jeff Meatball Yang
la source
1
C'est horrible. Je n'avais jamais mis mes données en danger comme ça. Qui sait si cela est correct pour toutes les heures de données, pas seulement celles que vous avez testées.
usr
@usr Oh, c'est correct, c'est juste un chiffre magique et ne devrait pas être utilisé pour cette raison. Si vous voulez vérifier son exactitude, fourrez simplement toutes les dates possibles pour une journée dans un tableau et vérifiez les résultats! Consultez également cet article pour plus d'informations.
ErikE
@ErikE bon point. Votre réponse offre la possibilité d'utiliser '12:00:00.003'ce que je pense est beaucoup mieux, cependant.
usr
6
SELECT CAST(CAST(GETDATE() AS DATE) AS DATETIME)
Byju
la source
4
Une option valide, oui. Suggéré plus d'une fois dans ce fil, cependant.
Andriy M
Honnêtement, cette solution est la plus facile à lire. Mon goto
BelgoCanadian
5

J'aime vraiment:

[date] = CONVERT(VARCHAR(10), GETDATE(), 120)

Le 120code de format contraindra la date dans la norme ISO 8601:

'YYYY-MM-DD' or '2017-01-09'

Super facile à utiliser dans dplyr ( R) et pandas ( Python)!

emehex
la source
3

IL FAUT SE MÉFIER!

Les méthodes a) et b) n'ont PAS toujours la même sortie!

select DATEADD(dd, DATEDIFF(dd, 0, '2013-12-31 23:59:59.999'), 0)

Production: 2014-01-01 00:00:00.000

select cast(convert(char(11), '2013-12-31 23:59:59.999', 113) as datetime)

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).

broslav
la source
1
.999 ne peut pas être stocké dans SQL Server dans une DATETIMEcolonne. 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.
Adam Wenger
Vous avez raison. Je ne voulais pas poster cela comme une réponse à la question OP, mais comme un commentaire pour les autres, mais je n'avais que 11 points de réputation et 15 sont nécessaires pour commenter.
broslav
Dans votre premier extrait de code, la constante de chaîne est implicitement convertie en datetime, dans votre second, elle reste une chaîne (et le 113 est simplement ignoré).
Andriy M
2

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é:

select date_only(dd)

L'implémentation de date_onlypeut être tout ce que vous aimez - maintenant, elle est abstraite et le code d'appel est beaucoup plus propre.

Anton Gogolev
la source
J'ai une fois conçu un déclencheur pour parcourir les temps des colonnes sélectionnées. Si les données ne peuvent pas être mauvaises, vous n'avez pas à les nettoyer.
Philip Kelley
2
Il y a un inconvénient à l'approche UDF, ils ne sont pas SARGable. S'il est utilisé dans des clauses JOINs ou WHERE, l'optimiseur ne peut pas utiliser INDEX pour améliorer les performances. Cependant, l'utilisation de l'approche DATEADD / DATEDIFF est SARGable et pourra bénéficier des INDEX. (Apparemment, la méthode FLOAT est également SARGable)
MatBailie
1
@MatBailie Je vous prie de différer! Les UDF ne sont certainement pas SARGables, mais ni Dateadd ni Convert to float! WHERE DateAdd(DateDiff(Column)) = @DateValuen'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.
ErikE
2

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.

Joel Coehoorn
la source
Merci, j'ai pensé que cela devait avoir été demandé auparavant. Étrange cependant, mes expériences ont montré que la méthode float est en fait plus lente de 3,5% sur SQL Server 2008 que la méthode dateadd (dd, 0, dateiff (dd, 0, getDate ())). J'ai exécuté mes tests plusieurs fois pour chaque méthode et le serveur de base de données n'était pas utilisé pour autre chose à l'époque.
Stephen Perelson
Disons simplement que je suis sceptique vis-à-vis des benchmarks effectués par quiconque n'a pas démontré qu'ils le font régulièrement et de manière très scientifique dans le cadre de leur travail. Même le benchmark de Thomas dans le lien par gbn a des problèmes évidents quand vous le regardez. Cela ne fait pas nécessairement mal, tout simplement pas définitif. La méthode moulage / plancher / moulage était le moyen le plus rapide accepté depuis très longtemps, et je pense que c'était une fois incontestablement vrai. Cela dit, je commence à le reconsidérer; en particulier pour SQL Server 2008, où il est de toute façon complètement inutile.
Joel Coehoorn
1
La méthode des chaînes est extrêmement facile à utiliser, à lire et à mémoriser. Ce sont des facteurs très importants que je pense que vous sous-estimez!
Ben
1
@JoelCoehoorn, le style de conversion 121 est appelé "ODBC Canonical". Il ne varie pas avec le classement ou les paramètres régionaux. L'astuce de chaîne est également facile à généraliser à l'année, l'année + le mois, le jour, l'heure ou la minute.
Ben
1
@Ben L'astuce de chaîne apprend aux développeurs à utiliser les conversions de chaînes. Ils fonctionnent , mais les mathématiques des dates sont de loin, bien supérieures, pour de nombreuses raisons, dont la moindre n'est pas la vitesse - mais encore plus, pour ce qu'apprendre à travailler avec les dates sous forme de chiffres confère au développeur et à ses capacités mentales être fluide avec la manipulation des nombres dans le code.
ErikE
2

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)

 CAST(
FLOOR( CAST( GETDATE() AS FLOAT ) )
AS DATETIME
)

la deuxième fois que j'ai trouvé cette solution ... j'ai saisi ce code

Carter Cole
la source
1
La conversion en float n'est pas sûre .
ErikE
2
CAST(round(cast(getdate()as real),0,1) AS datetime)

Cette méthode n'utilise pas de fonction de chaîne. Dateest 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.

shantanu singh chauhan
la source
1
Lancer comme flotteur n'est pas sûr .
ErikE
2

Pour moi, le code ci-dessous est toujours gagnant:

SELECT CONVERT(DATETIME, FLOOR(CONVERT(FLOAT,GETDATE())));
user1920017
la source
1
Essentiellement identique à la suggestion de @Gary McGill .
Andriy M
1
Lancer comme flotteur n'est pas sûr .
ErikE
2

sélectionnez CONVERTIR (char (10), GetDate (), 126)

Diego
la source
Quelle est la principale différence entre votre suggestion et la méthode mentionnée dans la réponse de @ broslav ou la méthode qui a été jugée la plus lente dans ce fil (même lien que dans la réponse acceptée)?
Andriy M
1

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:

create function dateonly (  @dt datetime )
returns datetime
as
begin
return cast(floor(cast(@dt as float))as int)
end
Aaron West
la source
1

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.

Dr. Drew
la source
Ils ne sont pas les mêmes. Les autres réponses ont suggéré de le transposer dans une date sans composante temporelle et de le laisser ainsi. Ma publication le définit à une date et heure à minuit. Il y a une grosse différence; essayez d'exporter vers MS Excel et vous verrez qu'il gère le datetime bien mieux que la date.
Dr.Drew
Le premier est exactement le même.
Mikael Eriksson
Ok, oui, je vois celui-là maintenant. Je me ferai un plaisir de retirer ma réponse en double, si nécessaire.
Dr.Drew
1

Je pense que si vous vous en tenez strictement à TSQLcela, c'est le moyen le plus rapide de tronquer le temps:

 select convert(datetime,convert(int,convert(float,[Modified])))

J'ai trouvé que cette méthode de troncature était environ 5% plus rapide que la DateAddméthode. Et cela peut être facilement modifié pour arrondir au jour le plus proche comme ceci:

select convert(datetime,ROUND(convert(float,[Modified]),0))
Jamie G
la source
La conversion en float n'est pas sûre .
ErikE
1

Ici, j'ai créé une fonction pour supprimer certaines parties d'un datetime pour SQL Server. Usage:

  • Le premier paramètre est le datetime à supprimer.
  • Le deuxième paramètre est un caractère:
    • s: arrondit aux secondes; supprime les millisecondes
    • m: tours à minutes; supprime les secondes et les millisecondes
    • h: arrondis à heures; supprime les minutes, les secondes et les millisecondes.
    • d: arrondis à jours; supprime les heures, les minutes, les secondes et les millisecondes.
  • Renvoie le nouveau datetime

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

Max Vargas
la source
Merci Andriy! Je ne savais pas que ma recommandation n'était pas aussi efficace. Au moins ça marche, mais vous avez raison.
Max Vargas
1

Juste au cas où quelqu'un chercherait ici une version Sybase car plusieurs des versions ci-dessus ne fonctionnaient pas

CAST(CONVERT(DATE,GETDATE(),103) AS DATETIME)
  • Testé dans I SQL v11 exécuté sur Adaptive Server 15.7
Alan
la source
Cela convient mieux en tant que modification de la réponse acceptée. Avec 20 autres réponses, cela sera enterré et presque introuvable. La réponse acceptée mentionne également l'utilisation cast: Pour SQL Server 2008+, vous pouvez CAST à ce jour. Ou utilisez simplement la date pour ne pas perdre de temps.
EWit
Il serait préférable de poster ceci comme une réponse à une question Sybase équivalente. S'il n'y a pas une telle question, vous êtes libre d'en créer une (et d'y répondre vous-même).
Andriy M
En outre, il est inutile de spécifier un troisième paramètre à CONVERT lorsque vous convertissez a datetimeen date: aucun de ceux-ci n'a un format inhérent.
Andriy M
0

Si possible, pour des choses spéciales comme celle-ci, j'aime utiliser les fonctions CLR.

Dans ce cas:

[Microsoft.SqlServer.Server.SqlFunction]
    public static SqlDateTime DateOnly(SqlDateTime input)
    {
        if (!input.IsNull)
        {
            SqlDateTime dt = new SqlDateTime(input.Value.Year, input.Value.Month, input.Value.Day, 0, 0, 0);

            return dt;
        }
        else
            return SqlDateTime.Null;
    }
tjeuten
la source
0

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.

CraigTP
la source
L'utilisation d'un UDF peut être utile dans certaines situations (comme lors du nettoyage des paramètres). Mais dans la plupart des situations, c'est une solution horrible - exécuter une UDF une fois pour chaque ligne est un moyen de simplement tuer les performances d'une requête, sans en avoir besoin!
ErikE
@ErikE - Je ne suis pas en désaccord, Erik, les UDF sont des tueurs de performances, c'est pourquoi je dis que si vous pouvez utiliser SQL Server 2008 ou supérieur et utiliser un type de données intégré qui le fait pour vous, ce sera la meilleure solution (à la fois en termes de réalisation de ce qui est requis et en termes de performances). Si vous êtes bloqué avec une ancienne version de SQL Server qui ne prend pas en charge cela nativement, vous allez abandonner quelque chose afin de répondre à vos besoins.
CraigTP
Vrai. Ce serait bien si le moteur de base de données nous donnait quelque chose qui était SARGable, mais plus facile à exprimer. En attendant, si vous êtes à la recherche d'une valeur qui est tout moment au cours d' une journée, cela est encore la meilleure solution (pour au moins les anciennes versions de SQL): 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.
ErikE
@ErikE - Pas de soucis, Erik. Lorsque j'ai utilisé des FDU, j'ai travaillé avec de petits ensembles de données où les performances ne sont pas primordiales, ou plus probablement j'ai filtré la requête par rapport au champ de date "brut" (pour garantir la sargabilité), mais en sélectionnant la colonne avec l'UDF appliqué. Comme il s'agit généralement de petits ensembles de données une fois filtrés, l'exécution de l'UDF sur ce petit nombre d'enregistrements n'est pas un tel problème de performances. Cela dit, vous soulevez un très bon point et j'ai mis à jour ma réponse pour refléter cela.
CraigTP
-4

J'utiliserais:

CAST
(
CAST(YEAR(DATEFIELD) as varchar(4)) + '/' CAST(MM(DATEFIELD) as varchar(2)) + '/' CAST(DD(DATEFIELD) as varchar(2)) as datetime
) 

Ainsi, vous créez efficacement un nouveau champ à partir du champ de date que vous avez déjà.

Jabu
la source
2
Pourquoi ferais-tu ça? Pensez-vous que l'extraction de bits d'undatetimedatetime 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'original datetime(la méthode DATEADD/ DATEDIFF)?
Andriy M
De plus, quels sont MMet DD? Il n'y a pas de telles fonctions dans SQL Server.
Andriy M