J'essaie de regrouper les enregistrements par semaine, en stockant la date agrégée comme premier jour de la semaine. Cependant, la technique standard que j'utilise pour arrondir les dates ne semble pas fonctionner correctement avec des semaines (bien qu'elle le fasse pendant des jours, des mois, des années, des trimestres et tout autre délai auquel je l'ai appliquée).
Voici le SQL:
select "start_of_week" = dateadd(week, datediff(week, 0, getdate()), 0);
Cela revient 2011-08-22 00:00:00.000
, qui est un lundi, pas un dimanche. Sélection des @@datefirst
retours 7
, qui est le code pour dimanche, afin que le serveur soit configuré correctement pour autant que je sache.
Je peux contourner cela assez facilement en changeant le code ci-dessus en:
select "start_of_week" = dateadd(week, datediff(week, 0, getdate()), -1);
Mais le fait que je doive faire une telle exception me met un peu mal à l'aise. Aussi, excuses si c'est une question en double. J'ai trouvé des questions connexes, mais aucune ne traitait spécifiquement de cet aspect.
la source
(@@DATEFIRST + DATEPART(DW, @SomeDate)) % 7
reste constant quel que soit le@@datefirst
réglage je pense. With Monday = 2.Réponses:
Pour expliquer pourquoi vous obtenez un lundi et non un dimanche:
Vous ajoutez un nombre de semaines à la date 0. Qu'est-ce que la date 0? 1900-01-01. Quel était le jour du 1900-01-01? Lundi. Donc, dans votre code, vous dites, combien de semaines se sont écoulées depuis le lundi 1er janvier 1900? Appelons cela [n]. OK, ajoutez maintenant [n] semaines au lundi 1er janvier 1900. Vous ne devriez pas être surpris que cela finisse par être un lundi.
DATEADD
n'a aucune idée que vous voulez ajouter des semaines, mais seulement jusqu'à ce que vous arriviez à un dimanche, il s'agit simplement d'ajouter 7 jours, puis d'ajouter 7 jours de plus, ... tout commeDATEDIFF
ne reconnaît que les limites qui ont été franchies. Par exemple, les deux renvoient 1, même si certaines personnes se plaignent qu'il devrait y avoir une logique sensée intégrée pour arrondir vers le haut ou vers le bas:Pour savoir comment obtenir un dimanche:
Si vous voulez un dimanche, choisissez une date de base qui n'est pas un lundi mais plutôt un dimanche. Par exemple:
Cela ne cassera pas si vous modifiez votre
DATEFIRST
paramètre (ou si votre code est en cours d'exécution pour un utilisateur avec un paramètre différent) - à condition que vous souhaitiez toujours un dimanche quel que soit le paramètre actuel. Si vous voulez que ces deux réponses à jive, vous devez utiliser une fonction qui ne dépend duDATEFIRST
réglage, par exempleDonc, si vous changez votre
DATEFIRST
réglage sur lundi, mardi, qu'as-tu, le comportement changera. Selon le comportement souhaité, vous pouvez utiliser l'une de ces fonctions:...ou...
Maintenant, vous avez beaucoup d'alternatives, mais laquelle fonctionne le mieux? Je serais surpris qu'il y ait des différences majeures, mais j'ai rassemblé toutes les réponses fournies jusqu'à présent et les ai passées à travers deux séries de tests - un bon marché et un cher. J'ai mesuré les statistiques du client car je ne vois pas les E / S ou la mémoire jouer un rôle dans la performance ici (bien que celles-ci puissent entrer en jeu en fonction de la façon dont la fonction est utilisée). Dans mes tests, les résultats sont:
Requête d'affectation "bon marché":
Requête d'attribution "coûteuse":
Je peux relayer les détails de mes tests si vous le souhaitez - en m'arrêtant ici car cela devient déjà assez long. J'ai été un peu surpris de voir que Curt est le plus rapide du haut de gamme, compte tenu du nombre de calculs et du code en ligne. Peut-être que je vais faire des tests plus approfondis et bloguer à ce sujet ... si vous n'avez aucune objection à ce que je publie vos fonctions ailleurs.
la source
Pour ceux qui doivent obtenir:
Lundi = 1 et dimanche = 7:
Dimanche = 1 et samedi = 7:
Ci-dessus, il y avait un exemple similaire, mais grâce au double "% 7", ce serait beaucoup plus lent.
la source
select (datediff(dd,5,cal.D_DATE)%7 + 1)
etselect (datediff(dd,6,cal.D_DATE)%7 + 1)
Pour ceux qui ont besoin de la réponse au travail et la création de fonction est interdite par votre DBA, la solution suivante fonctionnera:
Cela donne le début de cette semaine. Ici, je suppose que les dimanches sont le début des semaines. Si vous pensez que le lundi est le début, vous devez utiliser:
la source
Cela fonctionne à merveille pour moi:
la source
Googlé ce script:
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=47307
la source
Peut-être avez-vous besoin de ceci:
Ou
Fonction
la source
DATEPART(DW
dépend de@@datefirst
DATE
alors vous n'avez pas à faire de conversions sous-optimales versVARCHAR
et inversement juste pour supprimer toute composante temporelle accidentelle qui est passée.Time
valeurs.la source
Pour le basique (le dimanche de la semaine en cours)
Si la semaine précédente:
En interne, nous avons construit une fonction qui le fait mais si vous avez besoin de rapide et sale, cela le fera.
la source
Puisque la date julienne 0 est un lundi, ajoutez simplement le nombre de semaines au dimanche qui est le jour avant -1 Par exemple. sélectionnez dateadd (sem, dateiff (sem, 0, getdate ()), - 1)
la source
C'est ma logique. Définissez le premier de la semaine sur lundi, puis calculez quel est le jour de la semaine d'un jour donné, puis en utilisant DateAdd et Case, je calcule ce que la date aurait été le lundi précédent de cette semaine.
la source
Je n'ai aucun problème avec les réponses données ici, mais je pense que la mienne est beaucoup plus simple à mettre en œuvre et à comprendre. Je n'ai effectué aucun test de performance dessus, mais cela devrait être négligeable.
J'ai donc dérivé ma réponse du fait que les dates sont stockées dans le serveur SQL sous forme d'entiers (je ne parle que du composant de date). Si vous ne me croyez pas, essayez ce SELECT CONVERT (INT, GETDATE ()), et vice versa.
Maintenant, sachant cela, vous pouvez faire des équations mathématiques intéressantes. Vous pourrez peut-être en trouver un meilleur, mais voici le mien.
la source
@@DATEFIRST
est également 7, mais si vous@testDate
êtes le début de la semaine, cela renvoie une date qui est la veille.J'avais un problème similaire. Étant donné une date, je voulais obtenir la date du lundi de cette semaine.
J'ai utilisé la logique suivante: trouvez le numéro du jour de la semaine dans la plage de 0 à 6, puis soustrayez-le de la date d'origine.
J'ai utilisé: DATEADD (jour, - (DATEPART (jour de la semaine,) + 5)% 7,)
Puisque DATEPRRT (jour de la semaine,) renvoie 1 = dimanche ... 7 = samedi, DATEPART (jour de la semaine,) + 5)% 7 renvoie 0 = lundi ... 6 = dimanche.
En soustrayant ce nombre de jours de la date d'origine, on obtient le lundi précédent. La même technique pourrait être utilisée pour n'importe quel jour de départ de la semaine.
la source
J'ai trouvé cela simple et utile. Fonctionne même si le premier jour de la semaine est le dimanche ou le lundi.
DÉCLARER @BaseDate AS Date
SET @BaseDate = GETDATE ()
DÉCLARER @FisrtDOW AS Date
SELECT @FirstDOW = DATEADD (d, DATEPART (WEEKDAY, @ BaseDate) * -1 + 1, @BaseDate)
la source
Peut-être que je simplifie trop ici, et cela peut être le cas, mais cela semble fonctionner pour moi. Je n'ai pas encore rencontré de problèmes avec ça ...
la source
SET DATEFIRST
.DATEFIRST
(depuis trois ans et demi maintenant), et ne le fait toujours pas. Et vous devriez également éviter les formats régionaux commem/d/y
, même dans les scénarios où le m et le d sont identiques.