Beaucoup de participants au forum SQL Server se compliquent la vie avec des calculs bizarres, Ã trouver le premier ou dernier jour d’un index temporel, comme celui d’une semaine, d’un mois, ou d’un trimestre.
Ces calculs se font souvent à base d’extractions de sous-chaînes après avoir converti une date en varchar(n), et on aboutit donc à des choses abominables.
Voici donc une série de calculs de valeurs, uniquement à base de fonctions de date …
Oui, les dates se manipulent avec des fonctions de date, et non pas avec des fonctions de chaîne !
J’en profite au passage pour rappeler mon billet sur le choix des types de données …
La majorité des valeurs calculées ci-dessous repose sur la différence en semaines, mois, trimestres, …, entre la date courante et le 1er Janvier 1900.
En effet, on peut introduire directement cette date par un zéro dans les fonctions de date, que SQL Server caste automatiquement, et qui donne cette date.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | ------------------------------- -- Nicolas Souquet - 29/03/2011 ------------------------------- SELECT --*** Semaine DATEADD(week, DATEDIFF(week, 0, GETDATE()) - 1, 0) AS premier_jour_de_la_semaine_precedente , DATEADD(week, DATEDIFF(week, 0, GETDATE()), 0) AS premier_jour_de_la_semaine_courante , DATEADD(week, DATEDIFF(week, 0, GETDATE()) + 1, 0) AS premier_jour_de_la_semaine_prochaine --- , DATEADD(DAY, -1, DATEADD(week, DATEDIFF(week, 0, GETDATE()), 0)) AS dernier_jour_de_la_semaine_precedente , DATEADD(DAY, -1, DATEADD(week, DATEDIFF(week, 0, GETDATE()) + 1, 0)) AS dernier_jour_de_la_semaine_courante , DATEADD(DAY, -1, DATEADD(week, DATEDIFF(week, 0, GETDATE()) + 2, 0)) AS dernier_jour_de_la_semaine_prochaine --*** Mois , DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1, 0) AS premier_jour_du_mois_precedent , DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) AS premier_jour_du_mois_courant , DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) + 1, 0) AS premier_jour_du_mois_prochain --- , DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)) AS dernier_jour_du_mois_precedent , DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) + 1, 0)) AS dernier_jour_du_mois_courant , DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) + 2, 0)) AS dernier_jour_du_mois_prochain --*** Trimestre , DATEADD(quarter, DATEDIFF(quarter, 0, GETDATE()) - 1, 0) AS premier_jour_du_trimestre_precedent , DATEADD(quarter, DATEDIFF(quarter, 0, GETDATE()), 0) AS permier_jour_du_trimestre_courant , DATEADD(quarter, DATEDIFF(quarter, 0, GETDATE()) + 1, 0) AS premier_jour_du_trimestre_prochain --- , DATEADD(DAY, -1, DATEADD(quarter, DATEDIFF(quarter, 0, GETDATE()), 0)) AS dernier_jour_du_trimestre_precedent , DATEADD(DAY, -1, DATEADD(quarter, DATEDIFF(quarter, 0, GETDATE()) + 1, 0)) AS dernier_jour_du_trimestre_courant , DATEADD(DAY, -1, DATEADD(quarter, DATEDIFF(quarter, 0, GETDATE()) + 2, 0)) AS dernier_jour_du_trimestre_prochain --*** Semestre , DATEADD(MONTH, ((DATEDIFF(quarter, 0, GETDATE()) / 2) * 6) - 6, 0) AS premier_jour_du_semestre_precedent , DATEADD(MONTH, (DATEDIFF(quarter, 0, GETDATE()) / 2) * 6, 0) AS premier_jour_du_semestre_courant , DATEADD(MONTH, ((DATEDIFF(quarter, 0, GETDATE()) / 2) * 6) + 6, 0) AS premier_jour_du_semestre_prochain --- , DATEADD(DAY, -1, DATEADD(MONTH, (DATEDIFF(quarter, 0, GETDATE()) / 2) * 6, 0)) AS dernier_jour_du_semestre_precedent , DATEADD(DAY, -1, DATEADD(MONTH, ((DATEDIFF(quarter, 0, GETDATE()) / 2) * 6) + 6, 0)) AS dernier_jour_du_semestre_courant , DATEADD(DAY, -1, DATEADD(MONTH, ((DATEDIFF(quarter, 0, GETDATE()) / 2) * 6) + 12, 0)) AS dernier_jour_du_semestre_prochain --*** Annee , DATEADD(YEAR , DATEDIFF(YEAR, 0, GETDATE()) - 1, 0) AS premier_jour_annee_precedente , DATEADD(YEAR , DATEDIFF(YEAR, 0, GETDATE()), 0) AS premier_jour_annee_courante , DATEADD(YEAR , DATEDIFF(YEAR, 0, GETDATE()) + 1, 0) AS premier_jour_annee_suivante --- , DATEADD(DAY, -1, DATEADD(YEAR , DATEDIFF(YEAR, 0, GETDATE()), 0)) AS dernier_jour_annee_precedente , DATEADD(DAY, -1, DATEADD(YEAR , DATEDIFF(YEAR, 0, GETDATE()) + 1, 0)) AS dernier_jour_annee_courante , DATEADD(DAY, -1, DATEADD(YEAR , DATEDIFF(YEAR, 0, GETDATE()) + 2, 0)) AS dernier_jour_annee_suivante --*** Siècle , DATEADD(YEAR, -YEAR(GETDATE()) % 100, DATEADD(YEAR , DATEDIFF(YEAR, 0, GETDATE()), 0)) AS premier_jour_du_siecle_courant , DATEADD(YEAR, -YEAR(GETDATE()) % 100 + 100, DATEADD(DAY, -1, DATEADD(YEAR , DATEDIFF(YEAR, 0, GETDATE()), 0))) AS dernier_jour_du_siecle_courant |
J’ai eu un peu la flemme sur le siècle, et j’ai trouvé comme prétexte pour m’arrêter que cela ne doit pas présenter grand intérêt
Bon calculs sur les dates !
ElSüket
Bonjour,
Pensez-vous qu’il y ait plus simple que le SELECT ci-dessous pour renvoyer le 1er jour du mois correspondant à la date courante – 1 an => nous sommes le 28/11/17 et je souhaite obtenir le 01/11/16
SELECT DATEADD(MONTH,DATEDIFF(MONTH,0,DATEADD(YEAR,-1,GETDATE())),0)
salut Elusket
Merci beaucoup pour cette article qui est trés interéssant
par comptre a partir de SQL2008R2 il existe la fonction eomonth qui retourne le dernier jour du mois
on est a maintenant prés a la version 2016 existe il des autres fonctions qui peuvent appraissent et facilite le traitement du date
merci
Merci Abdallah.
Effectivement tu as raison; néanmoins il faut noter que ces nouvelles fonctions sont des invocations .NET, et qu’elles sont souvent un ersatz de ce que l’on peut faire en C# par exemple.
En ce qui concerne EOMONTH(), cette fonction a été introduite avec SQL Server 2012
A bientôt !
J’ai des problèmes de performance avec les fonctions date.
Si j’exécute la même requête avec :
DT > (CASE WHEN (MONTH({ fn CURDATE() }) – 3) DATEADD(month, DATEDIFF(month, 0, GETDATE()) – 3, 0)
J’ai un résultat en 1min30
Quelqu’un à une idée sur la différence ?
Et avec :
DT > (CASE WHEN (MONTH({ fn CURDATE() }) – 3) <= 0 THEN '01/' + CAST(12 – 3 + MONTH({ fn CURDATE() }) AS char(2))
+ '/' + CAST(YEAR({ fn CURDATE() }) – 1 AS char(4)) ELSE '01/' + CAST(MONTH({ fn CURDATE() }) – 3 AS char(2)) + '/' + CAST(YEAR({ fn CURDATE() }) AS char(4)) END) le résultat sort en 4sec
Bonjour,
merci à tous les deux de vos commentaires.
En ce qui concerne l’année fiscale, il me semble qu’en France c’est l’année civile.
Je me rappelle m’être renseigné là -dessus quand j’étudiais la possibilité d’ouvrir ma propre entreprise au mois d’Octobre 2009 : le plafond annuel de chiffre d’affaire était à ce moment là de 32000€, et si j’avais ouvert mon entreprise en tant qu’auto-entrepreneur, je n’aurai pas pu dépasser les 8000€ d’Octobre à Décembre, puisque c’est au pro-rata.
Je ne sais pas si en France il est possible pour les entreprise de choisir leur année fiscale comme c’est le cas aux États-Unis …
@++
select dateadd(month, datediff(month, 0, GETDATE()) – (12 + datepart(month, GETDATE()) – 10) % 12, 0),
dateadd(month, datediff(month, 0, GETDATE()) – (12 + datepart(month, GETDATE()) – 10) % 12 + 12, -1)
Salut Elsuket,
Je suis tombé sur cette article car j’ai des problèmes de perfs … et j’essai de réaliser la même chose pour l’année fiscale en cours.
Une idée pour éviter d’utiliser des CASE WHEN ELSE END ?
Merci dans tous les cas pour cette article
Ou plus simplement
SELECT GETDATE() -1 AS hier_avec_heure
SELECT CAST(GETDATE() -1 AS DATE) AS hier
Et le jour précédent (hier)
SELECT DATEADD(WEEKDAY, -1,GETDATE()) AS hier_avec_heure
SELECT CAST(DATEADD(WEEKDAY, -1,GETDATE()) AS DATE)AS hier
Merci beaucoup, j’en avais déjà implementé mais là c’est plus que complet.