Regex to allow ONLY zero before 2 decimal points - oracle

I want these to be valid
.10
0.10
.99
0.99
and this not valid
1
1.00
9.00
^\d{0,0}(.\d{1,2})?$
^\d{0,1}(.\d{1,2})?$
I want the user to be able to 0.99 but not 1.99
I am using this regex in a vendor basec system.
I get an error in the system, saying 0.11 is invalid using ^\d{0,0}(.\d{1,2})?$
All numbers 0.99 to 9.99 are valid using ^\d{0,1}(.\d{1,2})?$
I want the user to be able to enter .11 and 0.11 which I am cannot do
Help is parreciated.

If you are validating actual numbers then just use an inequality:
SELECT *
FROM yourTable
WHERE num < 1.00;
Otherwise, if you really have to validate number strings as being less than 1 and having 1 or 2 decimal places, with optional leading zero, then use ^0?\.\d{1,2}$:
SELECT *
FROM yourTable
WHERE REGEXP_LIKE(num, '^0?\.\d{1,2}$');

You do not need (slow) regular expressions and can use simple comparisons and, to check the number of decimal places, the ROUND function:
SELECT *
FROM table_name
WHERE value >= 0
AND value < 1
AND value = ROUND(value, 2)

Related

Express decimal with precision of 2 in KQL?

I have a value, expressed in bytes, being returned from an Azure Log Analytics query:
I want to convert this to megabytes and make it more human readable. In this case, "4.19 MB".
When I try to convert the byte value into megabyte, I can't seem to get KQL to add the desired precision of 2 places.
Tried:
RequestBodySize = strcat(round(RequestBodySize / 1000 / 1000, 2), ' MB') but this results in "4.0 MB".
How do I get this value to correctly reflect a precision of 2?
EDIT 1:
format_bytes(RequestBodySize, 2) returns "4 MB". No precision.
Same with `format_bytes(RequestBodySize, 2, 'MB')
I used a simple query to simulate the case and it works as expected for me.
In the first example, I added the unit to the field's name to maintain consistent value format that is aligned with the way values are projected in queries:
AzureDiagnostics
| where TimeGenerated > startofday(ago(20d))
| summarize volumeSizeMB = round(sum(_BilledSize)/pow(1024,2),2)
Results:
17.27
And when adding the unit to the value:
AzureDiagnostics
| where TimeGenerated > startofday(ago(20d))
| summarize volumeSize = strcat(round(sum(_BilledSize)/pow(1024,2),2), ' MB')
Results:
17.27 MB
If your issue persists and you don't see the expected precision, I suggest you open support case to have it investigated.
Use print format_bytes(12345678) to get 12 MB.
Use print format_bytes(12345678, 2) to get 11.77 MB.
Read the doc for more info.
Hi The answers above me are great,
just wanted to add one small input.
the reason you are not getting the fraction after the decimal is because you are dividing two integers.
to get a real number you will need to first convert one of the numbers to float or double, by using the todouble() toflout() https://learn.microsoft.com/en-us/azure/data-explorer/kusto/query/todoublefunction
RequestBodySize = strcat(round(todouble(RequestBodySize) / 1024 / 1024, 2), ' MB')
or, as suggested by Yossi, just multiply by 1.0
RequestBodySize = strcat(round(1.0 * RequestBodySize / 1024 / 1024, 2), ' MB')
try something like this:
| summarize GB = 1.0 * sum(TheThingsYouSub) / 1024 / 1024 / 1024 by SomeFilter

SQL Server Reporting: How calculate value based on the previous calculated value int the same column?

I'm trying to calculate a row value based on the previous row value in the same column within a report expression. I can't precalculate this from database since starting point of calculation is dependent from input parameters and values in a table should be recalculated dynamically within report itself.
In Excel analogical data and formula look like as it is shown below (starting point is always 100):
B C D E
Price PreviousPrice CalcValue Formula
1 NULL NULL 100
2 2.6 2.5 104 B2/C2*D1
3 2.55 2.6 102 B3/C3*D2
4 2.6 2.55 104 B4/C4*D3
5 2.625 2.6 105 B5/C5*D4
6 2.65 2.625 106 B6/C6*D5
7 2.675 2.65 107 B7/C7*D6
I tried to calculate expected values ("CalcValue" is the name of column where expression is set) like this:
=Fields!Price.Value/ PreviousPrice.Value * Previous(reportitems("CalcValue").Value))
but got an error "Aggregate functions can be used only on report items contained in page headers and footers"
Can you please advice whether expected result is achievable in my case and suggest a solution?
Thank you in advance!
Sadly I'm still facing with issue: calculated column does not consider previous calculated value. E.g., I added CalcVal field with 100 as default and tried to calculate using above approach, like: =previous(runningValue(Fields!CalcVal.Value, sum, "DataSet1") ) * Fields!Price.Value/Fields!PreviousPrice.Value.
But in this case it always multiples Fields!Price.Value/Fields!PreviousPrice.Value by 100..
For example CalcVal on Fly always show 200
=previous(runningValue(Fields!CalcVal.Value, sum, "DataSet1")) * 2
https://imgur.com/Wtg3Wsg
I tried with your sample data, here is how I achieved the results
Formula to use, You might have to take care of null values
=Fields!Price.Value/(Fields!PreviousPrice.Value*Previous(Fields!CalcValue.Value))
Edit: Update to answer after Op's comment
CalcValue is caluated with below formula i.e on the fly
=RunningValue(CountDistinct("Tablix6"),Count,"Tablix6"*100
and then Final value as below
=Fields!Price.Value/(Fields!PreviousPrice.Value*
Previous(RunningValue(CountDistinct("Tablix6"),Count,"Tablix6"))*100)

how to make sure to never get ora-01438: value larger than specified precision allowed for this column?

I'm doing a division for each record and updating a certain column with the result
so my sql looks something like this
update table1 set frequency = num/denom where id>XXX
my frequency data type is number(10,10)
Based on https://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#CNCPT1838
First, I'm not even sure why I get this data because the answer will always be 0.XXX, so giving 10 before the comma would be a plenty. Then the 10 after the comma should be okay too because it will truncate if the answer is bigger.
NUMBER(10, 10) means 10 digits and a scale of 10.
That means you have 10 digits right of the decimal point which means no digit left of it.
So having the table
CREATE TABLE t
(
test NUMBER (10, 10)
);
insert into t values (0.9999999999); will work, while
insert into t values (0.99999999999);will fail because the value is rounded up to 1.
So if num/denom is 1 or even larger you will get ORA-01438: value larger than specified precision allowed for this column.
But you will also get this error, if num/denom is larger then 0.99999999995 as oracle tries to round it to 1.
First of all, let me get this confusion around the precision and scale cleared out. According to the documentation, it is stated:
For numeric columns, you can specify the column as:
column_name NUMBER
Optionally, you can also specify a precision
(total number of digits) and scale (number of digits to the right of
the decimal point):
column_name NUMBER (precision, scale)
In your case:
frequency NUMBER(10,10)
This means, that the total number of digits is 10 and this means that the column can accommodate values from:
0.0000000001
to:
9999999999
This includes Integers up to 9999999999 (10 nines) and floats from 0.0000000001 (9 zeroes and a 1 at the end).
Now that we know this, let's proceed to the problem..
You need this query to never fail with ORA-01438:
update table1 set frequency = num/denom where id>XXX;
You can do the following check, on update time:
update table1
set frequency = CASE LENGTH(TRUNC(num/denom)) >=10
THEN TRUNC(num/denom, 10)
ELSE
ROUND(num/denom), 10 - LENGTH(TRUNC(num/denom))) --TRUNC
END
where id>XXX;
What this would do is check:
1. If the whole part of the division is more than or equal to 10; in that case, return only the first 10 digits (TRUNCATE).
2. If the whole part is less than 10; in that case ROUND the result to "10 - LENGTH_OF_WHOLE_PART" decimal places, but still within the precision of 10, which is the one of the column.
*Note: The ROUND above will actually ROUND the result, giving you an inaccurate value. If you need to get a raw truncation of the result, use TRUNCATE instead of ROUND above!
Cheers

Oracle regexp_like failing on FLOAT from view

I'm trying to use regexp_like to find and remove overly-precise floating point numbers.
select c from t order by c asc;
returns many results like this: 0.0000000012345678
Using regexp_like I can get results for two decimal places (0.25):
select * from t where REGEXP_LIKE(c,'^\d+\.\d{2}');
However, when I try anything more than two places, I get no results:
select * from t where REGEXP_LIKE(c,'^\d+\.\d{3}');
...
select * from t where REGEXP_LIKE(c,'^\d+\.\d{10}');
The only add'l info is that I'm selecting against a view of a second view and the column I'm searching (c, above) is designated as a FLOAT.
You can treat them as numbers. You can truncate the value to a fixed number of decimal places:
The TRUNC (number) function returns n1 truncated to n2 decimal places.
and then see if it matches. For example, to find any values with more than 2 significant digits after the decimal point:
select * from t where c != trunc(c, 2);
or to find those with more than 10 significant digits:
select * from t where c != trunc(c, 10);
I've used != rather than > in case you have negative values.
You can also use that as a filter in a delete/update, or as the set part of an update if you want to reduce the precision - though in that case you might want to use round() instead fo trunc().
When you use regexp_like you're doing an implicit conversion of your float value to a string, and as the docs for to_char() note:
If you omit fmt, then n is converted to a VARCHAR2 value exactly long enough to hold its significant digits.
which means that 0.25 becomes the string '.25', with no leading zero; which doesn't match even your first pattern.
You can allow for that leading zero not being there by using * instead of +, e.g. to find values with at least 10 significant digits after the decimal point:
select * from t where REGEXP_LIKE(c,'^\d*\.\d{10}');
or with exactly 10:
select * from t where REGEXP_LIKE(c,'^\d*\.\d{10}$');
etc.; but it seems simpler to treat them just as numbers rather than as strings.

SSRS 2005 Round(foo, 0) is rounding a decimal value of 12.6 to 12 instead of 13

I have a report field that can contain different types of data, therefore I need to do my rounding and formatting using functions.
In one case, I have a decimal(9,2) value storing hours that I need to display as minutes with zero decimal places.
Round(foo*60, 0), where foo = .01 (which is 0.6 when multiplied by 60), is outputting 1 like I would expect.
Round(foo*60, 0), where foo = .21 (which is 12.6 when multiplied by 60), is outputting 12 instead of 13.
Why? How can I get it to consistently use standard 4/5 rounding?
Take a look at this other stackoverflow question:
SQL Server Reporting Services Round() function
You are seeing Round to Even logic rather than mid point rounding.
This Wikipedia article has all the details about rounding:
Wikipedia Rounding Article
I can't reproduce your results. Perhaps you are hiding some other relevant details.
Declare #foo Decimal(9,2)
Set #foo = 0.21
Select Round(#Foo * 60, 0), #foo * 60
The output from the above code is 13.00 and 12.60 respectively.
Is it possible that the Foo column is a float, or that there is more precision in the foo column that you expect? For example, the following code produces 12 (instead of 13).
Declare #foo float
Set #foo = 0.208
Select Round(#Foo * 60, 0), #foo * 60, Round(#foo, 2)

Resources