2017-01-06 1 views
0

J'utilise la formule de Steve Kass pour obtenir le nième jour d'une semaine à la nième semaine du mois précédent pour une date donnée. Cela fonctionne très bien - mais je ne comprends vraiment pas ce que fait l'opérande du module dans la formule. Quelqu'un peut-il expliquer? Ive a essayé de fournir quelques faits connus ci-dessous:Explication du module pour la formule de Steve Kass de trouver le nième jour de la semaine à la neuvième semaine du mois

declare @svcDate as datetime= '1/6/2017', @myN as tinyint=4, @myD as tinyint=1 

declare @ret datetime; 
declare @first datetime -- First of the month of interest (no time part) 
declare @nth tinyint -- Which of them - 1st, 2nd, etc. 
declare @dow tinyint -- Day of week we want - this server is set to - 1 sun, 2 mon, 3 tue, 4 wed, 5 thur, 6 fri, 7 sat 
set @first = dateadd(month,-1,datefromparts(year(@svcDate), month(@svcDate), 1)) --first of last month 
set @nth = @myN 
set @dow = @myD 
--Select @first 12/1/2016 

set @ret = @first + 7*(@nth-1) 
--select @ret 12/22/2016 Thurs 
--datepart(weekday,@ret)=5 

set @ret= @ret + (7 + @dow - datepart(weekday,@ret))%7 

if(@ret IS NULL) 
    set @ret='1/1/2017'; 

select @ret 

select 3%7 --returns 3 

select convert(decimal(18,2),3)/convert(decimal(18,2),7) -- returns 0.42857142857142857142 

Répondre

0

L'opérateur modulo (%) effectue une division entière, et renvoie le reste.

Si vous vous souvenez des mathématiques élémentaires.

23 divided by 7 

7 va en 23 trois fois, avec un reste de 2

23 = (7 * 3) + 2 

La fonction de module seulement renvoie le reste après la division entière.


Et oui, nous nous attendons à l'expression 3%7 pour revenir 3

L'expression 10%7 sera également de retour 3.


EDIT

Q: Pourquoi est-opérateur module utilisé dans la formule? R: C'est un raccourci qui élimine beaucoup de contrôles conditionnels qui seraient nécessaires s'il n'était pas utilisé. (La formule peut être effectuée sans l'opération de module, mais elle est beaucoup plus courte avec elle.)

Dans la formule, la soustraction de weekday de @dow pourrait potentiellement être un nombre négatif de jours.

Et au point dans la formule, nous ne voulons pas un nombre de jours négatif. Nous voulons aller de l'avant un certain nombre de jours, pas en arrière.

Le raccourci consiste à ajouter sept jours au résultat de la soustraction. Cela nous garantit que nous n'aurons pas un nombre négatif de jours. Mais cette addition introduit un autre problème ... si la soustraction se traduisait par un nombre de jours positif, nous aurions maintenant une semaine entière plus ce nombre de jours. La division du module élimine les semaines complètes, nous laisse avec un entier compris entre 0 et 6, le nombre de jours que nous voulons ajouter à @first.


Nous pourrions obtenir le même résultat sans utiliser le module. Pour ce faire, nous ferions la soustraction de weekday de @dow. Si le résultat de la soustraction est négatif, alors ajouter 7.

Le module est juste un raccourci. La formule ajoute 7 dans tous les cas, puis soustrait 7 dans les cas où le résultat est supérieur à 6.

+0

Vous avez oublié de répondre à la question: qu'est-ce que ça fait ** dans la formule **. Est-ce nécessaire? –

+0

@PM: "ce que [l'opérateur de module] fait ** dans la formule **" est la même chose que l'opérateur de module fait partout ...il renvoie le reste d'une opération de division entière. La question à laquelle j'ai omis de répondre était une question qui n'a pas été posée ... ** "Pourquoi une opération de module est-elle nécessaire dans la formule" **. Je suppose que c'est dans la formule parce que la soustraction de '@ dow' et de' 'jour de semaine' est potentiellement négative. En ajoutant 7, puis en faisant fonctionner le module pour éliminer les semaines complètes, la formule renvoie un nombre de jours compris entre 0 et 6. – spencer7593

+0

Merci beaucoup, Spencer7593. Cela a du sens pour moi sur la sténographie et j'apprécie vraiment votre réponse très détaillée. A réussi à obtenir les petites cellules grises autour du concept. – user1795131