SQL code Interpretation "mod" and "CStr" - sql

I've been given an example of SQL code and I need to understand what this is doing before I convert it to another language.
Can someone explain to me in English what this code does please?
=IIF(Fields!Time.Value\60 < 10, "0" + CStr(Fields!Time.Value\60), CStr(Fields!Time.Value\60))
+ ":" +
IIF(Fields!Time.Value mod 60 < 10, "0" + FormatNumber(Fields!Time.Value mod 60,0), FormatNumber(Fields!Time.Value mod 60,0))
Many Many Thanks

It is taking a time (in seconds), and converting it to the format "mm:ss". For what it is worth, this looks more like VB script than SQL. Anyway, Cstr simply converts to string, mod gives the remainder of a division, e.g. 16 mod 10 gives you 6, 26 mod 10 would also give you 6.
The first part is using Fields!Time.Value/60 to get the time in minutes, then when this is number is less than 10, appending a 0 to the start:
| If seconds less than 10 | Append 0 to left of seconds | else just use seconds |
=IIF( Fields!Time.Value\60 < 10 , "0" + CStr(Fields!Time.Value\60), CStr(Fields!Time.Value\60))
The next part basically does the same with the seconds, part, but uses mod to get the number of seconds, for example, 97 seconds needs to be broken down to "01:37", so 97 / 60 is used to get the 1, then because this is less than 10, "0" is prepended to it, then 97 mod 60 is used to get the seconds, which gives 37, since this is over 10 nothing is prepended.

Related

Why are the variables are not taking the desired values

I have to check how many hundreds are there in a number and translate that number to letters. For example the number 700. I have done the following code:
DATA(lv_dmbtr) = ZDS_FG-DMBTR. //Declared local variable of type DMBTR, thus DMBTR=700.
lv_dmbtr = ZDS_FG-DMBTR MOD 100. //Finding how many times 700 is in 100 via MOD and putting the value in lv_dmbtr.
IF lv_dmbtr LE 9. //The value is less or equal than 9(if larger means that the DMBTR is larger than hundreds,
e.g. 8000)
lv_hundred = lv_dmbtr / 100. // Divide the 700 with 100, taking the number 7.
lv_hundred_check = lv_hundred MOD 1. // Then taking the value of 7 into the new variable, done in case the
lv_hundred is a decimal value, e.g. 7.32.
IF lv_hundred_check > 0.
CALL FUNCTION 'SPELL_AMOUNT'
EXPORTING
amount = lv_hundred_check
* CURRENCY = ' '
* FILLER = ' '
LANGUAGE = SY-LANGU
IMPORTING
in_words = lv_hundred_string // the value is put in the new string
EXCEPTIONS
not_found = 1
too_large = 2
OTHERS = 3.
ENDIF.
Now when I debugg the code, all the variables have the value 0. Thus, lv_dmbtr, lv_hundred, lv_hundred_check all have the value 0.
May anyone of you know where the problem may be?
Thank you in advance!
Sorry for writing a lot in the code, just wanted to clarify as much as I could what I had done.
yes so I want to display the value of a specific number 700-> seven, 1400-> four.
So the basic formula to get the hundred in a number is the following: Find out how many times 100 fits completely into your number with integer division.
99 / 100 = 0
700 / 100 = 7
701 / 100 = 7
1400 / 100 = 14
1401 / 100 = 14
Now you can simply take this number MOD 10 to get the the individual hundreds.
0 MOD 10 = 0
7 MOD 10 = 7
14 MOD 10 = 4
Keep in mind that ABAP, in contrast to many other programming languages, rounds automatically. So in code this would be:
CONSTANTS lc_hundred TYPE f VALUE '100.0'.
DATA(lv_number) = 1403.
DATA(lv_hundred_count) = CONV i( floor( ( abs( lv_number ) / lc_hundred ) ) MOD 10 ).

In TSQL, I am having difficulty getting Decimal(38,15) value to show 15 points after the decimal [duplicate]

Does anyone know why, using SQLServer 2005
SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,9),12499999.9999)
gives me 11.74438969709659,
but when I increase the decimal places on the denominator to 15, I get a less accurate answer:
SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,15),12499999.9999)
give me 11.74438969
For multiplication we simply add the number of decimal places in each argument together (using pen and paper) to work out output dec places.
But division just blows your head apart. I'm off to lie down now.
In SQL terms though, it's exactly as expected.
--Precision = p1 - s1 + s2 + max(6, s1 + p2 + 1)
--Scale = max(6, s1 + p2 + 1)
--Scale = 15 + 38 + 1 = 54
--Precision = 30 - 15 + 9 + 54 = 72
--Max P = 38, P & S are linked, so (72,54) -> (38,20)
--So, we have 38,20 output (but we don use 20 d.p. for this sum) = 11.74438969709659
SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,9),12499999.9999)
--Scale = 15 + 38 + 1 = 54
--Precision = 30 - 15 + 15 + 54 = 84
--Max P = 38, P & S are linked, so (84,54) -> (38,8)
--So, we have 38,8 output = 11.74438969
SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,15),12499999.9999)
You can do the same math if follow this rule too, if you treat each number pair as
146804871.212533000000000 and 12499999.999900000
146804871.212533000000000 and 12499999.999900000000000
To put it shortly, use DECIMAL(25,13) and you'll be fine with all calculations - you'll get precision right as declared: 12 digits before decimal dot, and 13 decimal digits after.
Rule is: p+s must equal 38 and you will be on safe side!
Why is this?
Because of very bad implementation of arithmetic in SQL Server!
Until they fix it, follow that rule.
I've noticed that if you cast the dividing value to float, it gives you the correct answer, i.e.:
select 49/30 (result = 1)
would become:
select 49/cast(30 as float) (result = 1.63333333333333)
We were puzzling over the magic transition,
P & S are linked, so:
(72,54) -> (38,29)
(84,54) -> (38,8)
Assuming (38,29) is a typo and should be (38,20), the following is the math:
i. 72 - 38 = 34,
ii. 54 - 34 = 20
i. 84 - 38 = 46,
ii. 54 - 46 = 8
And this is the reasoning:
i. Output precision less max precision is the digits we're going to throw away.
ii. Then output scale less what we're going to throw away gives us... remaining digits in the output scale.
Hope this helps anyone else trying to make sense of this.
Convert the expression not the arguments.
select CONVERT(DECIMAL(38,36),146804871.212533 / 12499999.9999)
Using the following may help:
SELECT COL1 * 1.0 / COL2

Set outcome of formula to working days

I would like to change the outcome of a SQL statement formula to 1, 2, 3, 4 or 5 (these are working days).
Example 1: when I have day 1, minus 2 days the outcome should be 4.
Example 2: when I have day 4, plus 2 days the outcome should be 1.
Example 3: when I have day 5, minus 20 days, the outcome should be 5
At the moment I'm using a table as shown below (I have the input and days-back and the output is what i want to see):
Input, days-back, output:
1 0 1
Input, days-back, output:
1 1 5
Input, days-back, output:
1 2 4
Input, days-back, output:
2 4 3
P.s. I do not have a date, only day numbers.
I hope you understand what I'm looking for :)
If you want to have "days-back" greater than 5 you need to use the following formula:
((Input + ((5*days-back)-1) - days-back) % 5) + 1
How this works - If you look at the prior formula you can see I'm adding 5 to input to make sure we are always positive before I subtract one and the days back. I then mod by 5 and add the one back in so that we go from 1 to 5 instead of 0 to 4
Since I don't know how large days-back is going to be I need something larger but I also need to have it not effect the mod 5 calculation so I just multiply it by 5. I then subtract one (so I can add it later and offset 0 to 4 to 1 to 5) and we are done.
prior answer below
I note I missed the 5 case -- here is the formula that works for that:
((Input + 4 - days-back) % 5) + 1
original answer
You need to use use modulus math. The formula you want is
(Input + 5 - days-back) % 5
Where % means modulus. In SQL Server you can use % in Oracle it is MOD, etc -- it depends on the platform.
For those that care here is my DB2 test code:
WITH TEST_TABLE(input, days_back) AS
(
VALUES
(1,0),
(1,1),
(1,2),
(2,4)
)
SELECT TEST_TABLE.*
MOD(INPUT+4-DAYS_BACK,5)+1
FROM TEST_TABLE

Rounding to a specific number ex: 4 ,5, 9 ,0 sql

I have prices that are going to be converted from one currency to several other currencies but once they are converted I would like to round them to a specific number.
The examples on what I need to round are the following :
Anything under 10 round to the next digit. For this I can just use the CEILING function.
Anything between 10-14 needs to rounded to 14.00. ex: 12.78 to 14.00
Between 14.01 and 15 needs to rounded to 15.00. ex: 14.25 to 15.00
Between 15.01 and 19 needs to be rounded to 19.00 ex: 17.35 to 19.00
Between 19.01 and 20 needs to rounded to 20.00. ex: 19.25 to 20.00
I know this seems a little weird but it is a specification I've been given for my project. To round to the next multiple of 5 I also understand but it is the 4 and 9 values that are really stumping me.
What formula would I need to use to obtain these numbers, or would it be easier to explode the number, grab the value before the decimal and do a case based on the criteria I stated above?
Thanks for your help!
A case seems to make the most sense but your "rounding" logic may look a little strange:
CASE
WHEN value < 10 THEN CEILING(value)
WHEN value <= 14 THEN 14
WHEN value <= 15 THEN 15
WHEN value <= 19 THEN 19
WHEN value <= 20 THEN 20
END
Or you could convert from floats to ints and use the modulus (%) operator:
CASE
WHEN value < 10 THEN CONVERT(int,CEILING(value))
WHEN CONVERT(int,CEILING(value)) % 5 = 0 -- 9.01 - 10, 14.01 - 15, 19.01 - 20, etc.
THEN CONVERT(int,CEILING(value))
WHEN CONVERT(int,CEILING(value)) % 5 <= 4 -- 10.01 - 14, 15.01 - 19, etc.
THEN CONVERT(int,FLOOR(value / 5)) * 5 + 4
END
Since you have slightly odd requirements (there is no simple formula to cover all your cases), then I think your best bet is to use a CASE...WHEN statement like this. Obviously tweak the precise inequalities based on your requirements:
SELECT CASE WHEN colVal < 10 THEN CEILING(colVal)
WHEN colVal <= 14 THEN 14
WHEN colVal <= 15 THEN 15
WHEN colVal <= 19 THEN 19
WHEN colVal <= 20 THEN 20
ELSE someotherval
END
EDIT: Based on the clarified requirements, D Stanley's answer with the modulo stuff is a better fit.

Understanding The Modulus Operator %

I understand the Modulus operator in terms of the following expression:
7 % 5
This would return 2 due to the fact that 5 goes into 7 once and then gives the 2 that is left over, however my confusion comes when you reverse this statement to read:
5 % 7
This gives me the value of 5 which confuses me slightly. Although the whole of 7 doesn't go into 5, part of it does so why is there either no remainder or a remainder of positive or negative 2?
If it is calculating the value of 5 based on the fact that 7 doesn't go into 5 at all why is the remainder then not 7 instead of 5?
I feel like there is something I'm missing here in my understanding of the modulus operator.
(This explanation is only for positive numbers since it depends on the language otherwise)
Definition
The Modulus is the remainder of the euclidean division of one number by another. % is called the modulo operation.
For instance, 9 divided by 4 equals 2 but it remains 1. Here, 9 / 4 = 2 and 9 % 4 = 1.
In your example: 5 divided by 7 gives 0 but it remains 5 (5 % 7 == 5).
Calculation
The modulo operation can be calculated using this equation:
a % b = a - floor(a / b) * b
floor(a / b) represents the number of times you can divide a by b
floor(a / b) * b is the amount that was successfully shared entirely
The total (a) minus what was shared equals the remainder of the division
Applied to the last example, this gives:
5 % 7 = 5 - floor(5 / 7) * 7 = 5
Modular Arithmetic
That said, your intuition was that it could be -2 and not 5. Actually, in modular arithmetic, -2 = 5 (mod 7) because it exists k in Z such that 7k - 2 = 5.
You may not have learned modular arithmetic, but you have probably used angles and know that -90° is the same as 270° because it is modulo 360. It's similar, it wraps! So take a circle, and say that its perimeter is 7. Then you read where is 5. And if you try with 10, it should be at 3 because 10 % 7 is 3.
Two Steps Solution.
Some of the answers here are complicated for me to understand. I will try to add one more answer in an attempt to simplify the way how to look at this.
Short Answer:
Example 1:
7 % 5 = 2
Each person should get one pizza slice.
Divide 7 slices on 5 people and every one of the 5 people will get one pizza slice and we will end up with 2 slices (remaining). 7 % 5 equals 2 is because 7 is larger than 5.
Example 2:
5 % 7 = 5
Each person should get one pizza slice
It gives 5 because 5 is less than 7. So by definition, you cannot divide whole 5items on 7 people. So the division doesn't take place at all and you end up with the same amount you started with which is 5.
Programmatic Answer:
The process is basically to ask two questions:
Example A: (7 % 5)
(Q.1) What number to multiply 5 in order to get 7?
Two Conditions: Multiplier starts from `0`. Output result should not exceed `7`.
Let's try:
Multiplier is zero 0 so, 0 x 5 = 0
Still, we are short so we add one (+1) to multiplier.
1 so, 1 x 5 = 5
We did not get 7 yet, so we add one (+1).
2 so, 2 x 5 = 10
Now we exceeded 7. So 2 is not the correct multiplier.
Let's go back one step (where we used 1) and hold in mind the result which is5. Number 5 is the key here.
(Q.2) How much do we need to add to the 5 (the number we just got from step 1) to get 7?
We deduct the two numbers: 7-5 = 2.
So the answer for: 7 % 5 is 2;
Example B: (5 % 7)
1- What number we use to multiply 7 in order to get 5?
Two Conditions: Multiplier starts from `0`. Output result and should not exceed `5`.
Let's try:
0 so, 0 x 7 = 0
We did not get 5 yet, let's try a higher number.
1 so, 1 x 7 = 7
Oh no, we exceeded 5, let's get back to the previous step where we used 0 and got the result 0.
2- How much we need to add to 0 (the number we just got from step 1) in order to reach the value of the number on the left 5?
It's clear that the number is 5. 5-0 = 5
5 % 7 = 5
Hope that helps.
As others have pointed out modulus is based on remainder system.
I think an easier way to think about modulus is what remains after a dividend (number to be divided) has been fully divided by a divisor. So if we think about 5%7, when you divide 5 by 7, 7 can go into 5 only 0 times and when you subtract 0 (7*0) from 5 (just like we learnt back in elementary school), then the remainder would be 5 ( the mod). See the illustration below.
0
______
7) 5
__-0____
5
With the same logic, -5 mod 7 will be -5 ( only 0 7s can go in -5 and -5-0*7 = -5). With the same token -5 mod -7 will also be -5.
A few more interesting cases:
5 mod (-3) = 2 i.e. 5 - (-3*-1)
(-5) mod (-3) = -2 i.e. -5 - (-3*1) = -5+3
It's just about the remainders. Let me show you how
10 % 5=0
9 % 5=4 (because the remainder of 9 when divided by 5 is 4)
8 % 5=3
7 % 5=2
6 % 5=1
5 % 5=0 (because it is fully divisible by 5)
Now we should remember one thing, mod means remainder so
4 % 5=4
but why 4?
because 5 X 0 = 0
so 0 is the nearest multiple which is less than 4
hence 4-0=4
modulus is remainders system.
So 7 % 5 = 2.
5 % 7 = 5
3 % 7 = 3
2 % 7 = 2
1 % 7 = 1
When used inside a function to determine the array index. Is it safe programming ? That is a different question. I guess.
Step 1 : 5/7 = 0.71
Step 2 : Take the left side of the decimal , so we take 0 from 0.71 and multiply by 7
0*7 = 0;
Step # : 5-0 = 5 ; Therefore , 5%7 =5
Modulus operator gives you the result in 'reduced residue system'. For example for mod 5 there are 5 integers counted: 0,1,2,3,4. In fact 19=12=5=-2=-9 (mod 7). The main difference that the answer is given by programming languages by 'reduced residue system'.
lets put it in this way:
actually Modulus operator does the same division but it does not care about the answer , it DOES CARE ABOUT reminder for example if you divide 7 to 5 ,
so , lets me take you through a simple example:
think 5 is a block, then for example we going to have 3 blocks in 15 (WITH Nothing Left) , but when that loginc comes to this kinda numbers {1,3,5,7,9,11,...} , here is where the Modulus comes out , so take that logic that i said before and apply it for 7 , so the answer gonna be that we have 1 block of 5 in 7 => with 2 reminds in our hand! that is the modulus!!!
but you were asking about 5 % 7 , right ?
so take the logic that i said , how many 7 blocks do we have in 5 ???? 0
so the modulus returns 0...
that's it ...
A novel way to find out the remainder is given below
Statement : Remainder is always constant
ex : 26 divided by 7 gives R : 5
This can be found out easily by finding the number that completely divides 26 which is closer to the
divisor and taking the difference of the both
13 is the next number after 7 that completely divides 26 because after 7 comes 8, 9, 10, 11, 12 where none of them divides 26 completely and give remainder 0.
So 13 is the closest number to 7 which divides to give remainder 0.
Now take the difference (13 ~ 7) = 5 which is the temainder.
Note: for this to work divisor should be reduced to its simplest form ex: if 14 is the divisor, 7 has to be chosen to find the closest number dividing the dividend.
As you say, the % sign is used to take the modulus (division remainder).
In w3schools' JavaScript Arithmetic page we can read in the Remainder section what I think to be a great explanation
In arithmetic, the division of two integers produces a quotient and a
remainder.
In mathematics, the result of a modulo operation is the
remainder of an arithmetic division.
So, in your specific case, when you try to divide 7 bananas into a group of 5 bananas, you're able to create 1 group of 5 (quotient) and you'll be left with 2 bananas (remainder).
If 5 bananas into a group of 7, you won't be able to and so you're left with again the 5 bananas (remainder).