Get fraction between x.66 and x.99 - sql

I'm trying to make a query - (CASE - WHEN statement):
--all cols are numbers
case when round((O.POCET - O.P_DEL - O.P_DEL_DOD - O.P_FAK - O.P_VYD - O.P_OBJ)/SK.VELKE_BAL,3)
between 0.66 and 0.99 then 1
when round((O.POCET - O.P_DEL - O.P_DEL_DOD - O.P_FAK - O.P_VYD - O.P_OBJ)/SK.DOD_BAL,3)
between 0.66 and 0.99 then 2
else 0 end
It's working fine, but i need to get numbers between 1.66-1.99, 2.66-2.99 and so on...
IF i use LIKE, i can get the fraction, but not between theese numbers.
How can i solve this ?

If you just want it when the decimal part of the (positive) number is between a range then use the MOD function:
CASE
WHEN MOD(your_sum1, 1) BETWEEN 0.66 AND 0.99
THEN 1
WHEN MOD(your_sum2, 1) BETWEEN 0.66 AND 0.99
THEN 2
ELSE 0
END
db<>fiddle here

Related

Snowflake CEIL Function - round up to next 0.1 kilometer

I have a column containing measurement values in meters.
I want to round them up (ceil) them to the next 100m and return it as a km value.
Special thing is: if the original value is a "round" number (100m increment) it should be ceiled up to the next 100m increment (see line 3 in the example below).
Example:
meter_value kilometer_value
1111 1.2
111 0.2
1000 1.1
I think I can get the first two lines by doing:
ceil(meter_value/1000,1) as kilometer_value
The solution I thought of to fix the edge case in line three is to just add 1 meter always:
ceil((meter_value+1)/1000,1) as kilometer_value
It seems a bit clumsy, is there a better way/alternative function to archive this?
You can check to see if it's divisible by 100 and only add one if it is:
ceil(((meter_value + iff(meter_value % 100 = 0, 1, 0))/1000), 1)
This will prevent situations where (if decimal parts are allowed) adding 1 to a value of 999.5 would not be accurate if adding one all the time.
Greg's answer is good, simpler to read to me would be to
divide by 100
floor
add 1
ceil
divide by 10
select
column1 as meter_value
,ceil(((meter_value + iff(meter_value % 100 = 0, 1, 0))/1000), 1) as greg
,ceil(floor(meter_value/100)+1)/10 as simeon
from values
(1111)
,(111)
,(1000)
,(1)
,(0)
;
METER_VALUE
GREG
SIMEON
1,111
1.2
1.2
111
0.2
0.2
1,000
1.1
1.1
1
0.1
0.1
0
0.1
0.1
do we want to mention negative values? I mean it distance, so it's a directionless magnitude, right?
anyway with negative value, both our methods the +1 forces the boundary case to be wrong.
Actually:
Once you have floored adding the 1 or 0.1 if you divide by 1000 vs 100 first, you don't need to ceil at all
thus two short forms can be:
,ceil(floor(meter_value/100)+1)/10 as version_a
,(floor(meter_value/100)+1)/10 as version_b
,floor(meter_value/1000,1)+0.1 as version_c

Calculating a total cost based on how many stripes someone wants on their clothes

I'm trying to make it so that if someone wants 3 or less stripes on their shorts it costs 50 cent per stripe on top of the 5.50 base cost for a pair of shorts and then every stripe after the third costs 2 euro each. It works if they chose 3 or less but once I enter any stripe amount above 3 it just displays the base 5.50 cost for the shorts. Not sure what to do any help is appreciated.
I have declared all my variables correctly, I assume the problem is with the code below
'calculate cost of Shorts
If mskShortStripes.Text <= 3 Then
dblTotalShorts += CDbl(mskShorts.Text * 5.5) + (mskShortStripes.Text * 0.5)
ElseIf mskShortStripes.Text > 3 Then
dblTotalShorts += CDbl(mskShorts.Text * 5.5) + (mskShortStripes.Text <= 3 * 0.5) + (mskShortStripes.Text > 3 * 2)
End If
You're asking for trouble working with the .Text property directly as if it were a number. It is not. Fun things happen when the value in your control is not actually a number.
Use Integer.TryParse to convert that string to a number:
Dim numberOfStripes As Integer
If Integer.TryParse(mskShortStripes.Text, numberOfStripes) Then
If numberOfStripes >= 0 Then
' ... now do some math in here with the "numberOfStripes" variable ...
Else
MessageBox.Show("Number of Stripes can't be negative!")
End If
Else
MessageBox.Show("Invalid Number of Stripes!")
End If

SAS - PROC SQL - Case When arithmetic not making sense

In SAS Proc SQL, I am using this Case statement to try to mark policies that have differences other than .015 per year:
CASE WHEN (MOD1 - MOD0) NOT = .015 THEN 2
WHEN (MOD2 - MOD1) NOT = .015 THEN 3
WHEN (MOD3 - MOD2) NOT = .015 THEN 4
WHEN (MOD4 - MOD3) NOT = .015 THEN 5
ELSE 0 END
The weird thing is it doesn't work when it feels like it should. ( e.g. mod1 = .955 and mod0 = .94 but the first statement believes its not .015) At first I believed it to be an issue with digits but that never worked.
Oddly enough this does work and I don't know why.
CASE WHEN (MOD1 - MOD0) NOT = (1- .985) THEN 2
WHEN (MOD2 - MOD1) NOT = (1- .985) THEN 3
WHEN (MOD3 - MOD2) NOT = (1- .985) THEN 4
WHEN (MOD4 - MOD3) NOT = (1- .985) THEN 5
ELSE 0 END
But this doesn't work
CASE WHEN (MOD1 - MOD0) NOT = (.2- .185) THEN 2
WHEN (MOD2 - MOD1) NOT = (.2- .185) THEN 3
WHEN (MOD3 - MOD2) NOT = (.2- .185) THEN 4
WHEN (MOD4 - MOD3) NOT = (.2- .185) THEN 5
ELSE 0 END
I have workarounds to get around any of these (including using data steps) so I'm not really looking for solutions to the issue but more answers as to what is going on here. I like to understand why things don't work rather than just knowing what I can and can't do.
Thanks!
The problem is probably floating point arithmetic. Exact comparisons to floats is troublesome. Try something like this:
CASE WHEN ABS((MOD1 - MOD0) - 0.015) > 0.00001 THEN 2
WHEN ABS((MOD2 - MOD1) - 0.015) > 0.00001 THEN 3
WHEN ABS((MOD3 - MOD2) - 0.015) > 0.00001 THEN 4
WHEN ABS((MOD4 - MOD3) - 0.015) > 0.00001 THEN 5
ELSE 0
END
The 0.00001 is arbitrary. It is just some small number.
You can use round function:
CASE WHEN round(MOD1 - MOD0,.0001) NOT = .015 THEN 2
WHEN round(MOD2- MOD1,.0001) NOT = .015 THEN 3
WHEN round(MOD3 - MOD2,.0001) NOT = .015 THEN 4
WHEN round(MOD4 - MOD3,.0001) NOT = .015 THEN 5
ELSE 0 END

How to use index match when you have 2 values?

I have a list with 300 names codes and each of these names have more than 1 value, e.g.,
CODE - VALUE
300 - 1
300 - 2
300 - 3
400 - 1
400 - 2
For each code, I want to return the greatest value, and after that I want to transform this greatest value into his name, e.g.,
CODE - VALUE - NAME
300 - 1 - alpha
300 - 2 - beta
300 - 3 - gamma
400 - 1 - theta
400 - 2 - sigma
So for code “300” I want to return “gamma” and for code “400” I want to return “sigma”.
Any thoughts?
Regards
place the following formula in F1 and the code you are looking for in E1. This assumes your second table is located in A1:C5. Adjust ranges to suit your data. Avoid full column references within the aggregrate function.
=INDEX(C:C,AGGREGATE(14,6,ROW(A1:A5)/((A1:A5=E1)*(B1:B5=AGGREGATE(14,6,B1:B5/(A1:A5=E1),1))),1))

change specific data of column

I have a table in which 10 record, now i want to update specific column data, means some part some column data and some not, for example in row 1 i want to change std with standard and other data will remain same, change same thing in all row in a single query. can it will be possible? and remember we cant remove and add cell again because it will change id
id - col1 - col2
1 - A - std abcad
2 - B - std bcddsad
3 - C - std avadsad
4 - A - std abcdsad
5 - B - std bcddsa
6 - C - std avadsad
7 - A - std abcdsd
8 - B - std bcddsds
9 - C - std avadsd
You can use the replace function for this
Update
table
Set
col2 = Replace(col2, 'std', 'standard');
UPDATE tblName
SET Column .WRITE('Standard',(CHARINDEX('std',Column,1)-1),LEN('std'))