Dans MS SQL 2000 et 2005, étant donné une date/heure telle que '2008-09-25 12:34:56', quelle est la façon la plus efficace d'obtenir une date et heure contenant uniquement '2008-09-25'?
Dupliqué ici .
Je dois admettre que je n'avais jamais vu la conversion plancher-flotteur montrée par Matt auparavant. J'ai dû tester cela.
J'ai testé une sélection pure (qui renverra la date et l'heure, et ce n'est pas ce que nous voulons), la solution régnante ici (plancher flottant), une `` naïve '' commune mentionnée ici (stringconvert) et celle mentionnée ici que j'étais en utilisant (car je pensais que c'était le plus rapide).
J'ai testé les requêtes sur un serveur de test MS SQL Server 2005 fonctionnant sur un serveur Win 2003 SP2 avec un processeur Xeon 3GHz fonctionnant sur la mémoire max (32 bits, donc c'est environ 3,5 Go). C'est la nuit où je suis donc la machine tourne au ralenti presque sans charge. J'ai tout pour moi.
Voici le journal de mon test en sélectionnant dans une grande table contenant des horodatages variant jusqu'au niveau de la milliseconde. Cet ensemble de données particulier comprend des dates s'étalant sur plus de 2,5 ans. Le tableau lui-même compte plus de 130 millions de lignes, c'est pourquoi je me limite au premier million.
SELECT TOP 1000000 CRETS FROM tblMeasureLogv2
SELECT TOP 1000000 CAST(FLOOR(CAST(CRETS AS FLOAT)) AS DATETIME) FROM tblMeasureLogv2
SELECT TOP 1000000 CONVERT(DATETIME, CONVERT(VARCHAR(10), CRETS, 120) , 120) FROM tblMeasureLogv2
SELECT TOP 1000000 DATEADD(DAY, DATEDIFF(DAY, 0, CRETS), 0) FROM tblMeasureLogv2
Temps d'analyse et de compilation SQL Server: temps CPU = 0 ms, temps écoulé = 1 ms.
(1000000 ligne (s) affectée (s)) Table 'tblMeasureLogv2'. Nombre de balayages 1, lectures logiques 4752, lectures physiques 0, lectures anticipées 0, lob lectures logiques 0, lob physiques lectures 0, lob lectures anticipées lisent 0.
Temps d'exécution SQL Server: temps CPU = 422 ms, temps écoulé = 33803 ms.
(1000000 ligne (s) affectée (s)) Table 'tblMeasureLogv2'. Nombre de balayages 1, lectures logiques 4752, lectures physiques 0, lectures anticipées 0, lob lectures logiques 0, lob physiques lectures 0, lob lectures anticipées lisent 0.
Temps d'exécution SQL Server: temps CPU = 625 ms, temps écoulé = 33545 ms.
(1000000 ligne (s) affectée (s)) Table 'tblMeasureLogv2'. Nombre de balayages 1, lectures logiques 4752, lectures physiques 0, lectures anticipées 0, lob lectures logiques 0, lob physiques lectures 0, lob lectures anticipées lisent 0.
Temps d'exécution SQL Server: temps CPU = 1953 ms, temps écoulé = 33843 ms.
(1000000 ligne (s) affectée (s)) Table 'tblMeasureLogv2'. Nombre de balayages 1, lectures logiques 4752, lectures physiques 0, lectures anticipées 0, lob lectures logiques 0, lob physiques lectures 0, lob lectures anticipées lisent 0.
Temps d'exécution SQL Server: temps CPU = 531 ms, temps écoulé = 33440 ms. Temps d'analyse et de compilation SQL Server: temps CPU = 0 ms, temps écoulé = 1 ms.
Temps d'exécution SQL Server: temps CPU = 0 ms, temps écoulé = 1 ms.
Que voyons-nous ici?
Concentrons-nous sur le temps CPU (nous regardons la conversion), et nous pouvons voir que nous avons les chiffres suivants:
Pure-Select: 422
Floor-cast: 625
String-conv: 1953
DateAdd: 531
D'après cela, il me semble que le DateAdd (au moins dans ce cas particulier) est légèrement plus rapide que la méthode au sol.
Avant d'y aller, j'ai exécuté ce test plusieurs fois, avec l'ordre des requêtes modifié, des résultats identiques.
Est-ce quelque chose d'étrange sur mon serveur, ou quoi?
Select DateAdd(Day, DateDiff(Day, 0, GetDate()), 0)
DateDiff (Day, 0, GetDate ()) est identique à DateDiff (Day, '1900-01-01', GetDate ())
Puisque DateDiff renvoie un entier, vous obtiendrez le nombre de jours qui se sont écoulés depuis le 1er janvier 1900. Vous ajoutez ensuite ce nombre entier de jours au 1er janvier 1900. L'effet net supprime la composante de temps.
Je dois également mentionner que cette méthode fonctionne pour n'importe quelle partie date/heure (comme l'année, le trimestre, le mois, le jour, l'heure, la minute et la seconde).
Select DateAdd(Year, DateDiff(Year, 0, GetDate()), 0)
Select DateAdd(Quarter, DateDiff(Quarter, 0, GetDate()), 0)
Select DateAdd(Month, DateDiff(Month, 0, GetDate()), 0)
Select DateAdd(Day, DateDiff(Day, 0, GetDate()), 0)
Select DateAdd(Hour, DateDiff(Hour, 0, GetDate()), 0)
Select DateAdd(Second, DateDiff(Second, '20000101', GetDate()), '20000101')
Le dernier, pendant quelques secondes, nécessite une manipulation spéciale. Si vous utilisez le 1er janvier 1900, vous obtiendrez une erreur.
La différence de deux colonnes datetime a provoqué un dépassement lors de l'exécution.
Vous pouvez contourner cette erreur en utilisant une date de référence différente (comme le 1er janvier 2000).
select cast(floor(cast(@datetime as float)) as datetime)
Fonctionne parce que la coulée d'un datetime pour flotter donne le nombre de jours (y compris les fractions de jour) depuis le 1er janvier 1900. Le plancher supprime les jours fractionnaires et laisse le nombre de jours entiers, qui peuvent ensuite être restitués en datetime.
dans SQL Server 2012, utilisez
select cast(getdate() as date)
select cast(getdate()as varchar(11))as datetime
Pour obtenir AAAA-MM-JJ, utilisez:
select convert(varchar(10), getdate(), 120)
Edit: Oups, il veut un DateTime au lieu d'une chaîne. L'équivalent de TRUNC () dans Oracle. Vous pouvez reprendre ce que j'ai publié et le restituer à un DateTime:
select convert(datetime, convert(varchar(10), getdate(), 120) , 120)
CAST(FLOOR(CAST(yourdate AS DECIMAL(12, 5))) AS DATETIME)
est de loin le meilleur. vous pouvez voir la preuve et les tests quand obtenir la date sans heure sur le serveur SQL
CONVERT, FLOOR et DATEDIFF fonctionneront de la même manière.
Comment renvoyer la partie date uniquement à partir d'un type de données datetime SQL Server
Trois méthodes décrites dans le lien ci-dessous. Je n'ai pas testé les performances pour déterminer laquelle est la plus rapide.