I want to use trunc() on a BigQuery "numeric" string column to truncate it from 3 decimals to 2 decimals.
This works when the string is specified inside trunc:
select
"yey" as x,
trunc(numeric '50.239', 2) as trunced
x trunced
1 yey 50.23
But if I want to run this on a table it doesn't work:
with t as(
select
"yey" as x,
'50.239' as y
)
select x, trunc(numeric y, 2) as y_trunc from t
And produces the error Syntax error: Expected ")" but got identifier "y" at [7:25]
Does anybody know what's going on?
numeric '50.239' is a numeric literal representation, not type casting. You should use cast(y as numeric) if you want to convert a string column to a numeric column.
with t as(
select
"yey" as x,
'50.239' as y
)
select x, trunc(cast(y as numeric), 2) as y_trunc from t
references
NUMERIC literals
You can construct NUMERIC literals using the NUMERIC keyword followed by a floating point value in quotes.
Examples:
SELECT NUMERIC '0';
SELECT NUMERIC '123456';
SELECT NUMERIC '-3.14';
Related
I'm trying to create a new column (y) from another column (x) - my aim is to extract the numeric value after the 1st space of the string from the right-hand side, and if there is no numeric value after the space, then NULL.
I used the following SQL query below; however, the query extracted both numeric and non-numeric after the space into the new column (y) - please see the first image below. I have also attempted to use case statement but have yet to achieve the required output.
SELECT x, SUBSTR(x, INSTR(x,' ', -1) + 1) AS y
FROM <table_name>;
I would like the table to return:-
Thanks for your help in advance!
You could try regular expression function REGEXP_SUBSTR
SELECT x, REGEXP_SUBSTR (x, '(\s)(\d+)$') AS y
FROM <table_name>
Please check demo here: http://sqlfiddle.com/#!4/7bc0ee/4866
If you want to keep your SUBSTRING idea, you can use VALIDATE_CONVERSION to check whether your substring is numeric or not.
Then a CASE will select this substring or NULL if not numeric:
SELECT x,
CASE WHEN VALIDATE_CONVERSION(SUBSTR(x, INSTR(x,' ', -1) + 1) AS NUMBER) = 1
THEN SUBSTR(x, INSTR(x,' ', -1) + 1)
ELSE NULL END AS y
FROM yourtable;
Try out db<>fiddle
Here the documentation of VALIDATE_CONVERSION
I have a 10 Character length values in a column in SQL Server. I need to split that column at fixed length and remove the leading zeros and add a - after each of the values.
I am able to split the values by using Substring and converting them to int. It is working well.
However, when I try to concatenate it is failing. Appreciate if you can help.
SELECT TOP 1 R.COL1, CAST(SUBSTRING(R.COL1,1,1) AS int) AS F1,CAST(SUBSTRING(R.COL1,2,5) AS int) AS F2,CAST(SUBSTRING(R.COL1,7,4) AS int) AS F3 CAST(SUBSTRING(R.COL1,1,1) AS int) +'-' +CAST(SUBSTRING(R.COL1,2,5) AS int) +'-' + CAST(SUBSTRING(R.COL1,7,4) AS int) AS finalString FROM MYTABLE R
If the value for COL1 IS 1012950001 the finalString I am expecting is 1-1295-1
however the result I am getting from the above query is 1297 as it is adding all the values.
Appreciate if you can help.
You can't use the + operator with a numerical data type and a varchar that cannot implicitly be converted to that data type. Something like 1 + 'a' isn't going to work, as 'a' isn't an int, and can't be implicitly converted to one.
If you are mixing data types, then use CONCAT, which implicitly converts each part into a (n)varchar:
CONCAT({Numerical Expression},'a',{Other varchar Expression})
You can use concat method to concatenate the substring value
select
concat(CAST(SUBSTRING('1012950001',1,1) AS int), '-',
CAST(SUBSTRING('1012950001',2,5) AS int), '-',
CAST(SUBSTRING('1012950001',7,4) AS int)) AS finalString
This will give you the expected result '1-1295-1'
I am trying to create a SQL UDF that takes a decimal number as an argument but if I pass in a number with a different number of decimal places I get an error, even if the number has a smaller number of digits to the right of the decimal point.
Here is a example of the problem:
CREATE OR REPLACE TABLE EXAMPLE (
COL1 NUMBER(7,5)
);
INSERT INTO EXAMPLE VALUES (9.12),(10.467),(11.6),(12.01234);
CREATE OR REPLACE FUNCTION LESS_THAN(DATA1 NUMBER(7,5))
RETURNS TABLE (COL1 NUMBER(7,5))
as
$$
SELECT COL1 FROM EXAMPLE WHERE COL1 < DATA1
$$
;
select * from table(LESS_THAN(11.3)); --Error: SQL compilation error: error line 1 at position 20 Invalid argument types for function 'LESS_THAN': (NUMBER(3,1))
select * from table(LESS_THAN(9.85)); --Error: SQL compilation error: error line 1 at position 20 Invalid argument types for function 'LESS_THAN': (NUMBER(3,2))
select * from table(LESS_THAN(10.85001)); --Works
I would like to be able to create a UDF that allows any decimal to be accepted.
Any thoughts?
Thanks
Try casting the inputs to NUMBER(7,5). For example:
select * from table(LESS_THAN('11.3'::NUMBER(7,5)));
select * from table(LESS_THAN( 11.3 ::NUMBER(7,5)));
You can use this system function to observe the types:
select 11.3 x, system$typeof(x); -- NUMBER(3,1)
select 11.30 x, system$typeof(x); -- NUMBER(3,1)
select 11.30 ::NUMBER(7,5) x, system$typeof(x); -- NUMBER(7,5)
select '11.30'::NUMBER(7,5) x, system$typeof(x); -- NUMBER(7,5)
I am trying to convert bit varyingto numeric (decimal value) in postgresql
select cast('10110101110110010100110001101010100111011011010000000101'::bit varying as numeric);
I have tried the cast function but getting below error.
ERROR: cannot cast type bit varying to numeric LINE 1: select
cast('10110101110110010100110001101010100111011011010...
^
********** Error **********
ERROR: cannot cast type bit varying to numeric SQL state: 42846
Character: 8
Output should be : 5429503678976. Any suggestions
EDIT: I do not know the max value so can not use
select b'10110101110110010100110001101010100111011011010000000101'::bigint
Thanks
You could break it up into individual bits, convert those to the appropriate numeric values and then sum them together:
with data(d) as (VALUES (B'10110101110110010100110001101010100111011011010000000101') )
select sum(parts) FROM (
SELECT get_bit(d, length(d) - n)::numeric * pow(2::numeric, n-1) as parts
from data, generate_series(1, length(d), 1) g(n)
) sub
;
sum
------------------------------------
51185893014090757.0000000000000000
(1 row)
Note that this gives me the same answer as select b'10110101110110010100110001101010100111011011010000000101'::bigint; but it should work for larger values as well, where bigint would be out of range.
You could turn it into a function:
CREATE OR REPLACE FUNCTION bitstring_to_numeric(l_bit_string varbit)
RETURNS numeric AS $$
SELECT sum(parts) FROM (
SELECT get_bit(l_bit_string,
length(l_bit_string) - n)::numeric * pow(2::numeric, n-1) as parts
from generate_series(1, length(l_bit_string), 1) g(n)
) sub
$$ LANGUAGE SQL
IMMUTABLE;
select bitstring_to_numeric(B'10110101110110010100110001101010100111011011010000000101');
bitstring_to_numeric
------------------------------------
51185893014090757.0000000000000000
I'm trying to get the max value from a text field. All but two of the values are numbers with a single decimal. However, two of the values have something like 8.2.10. How can I pull back just the integer value? The values can go higher than 9.n, so I need to convert this field into a number so that I can get the largest value returned. So all I want to get back is the 8 from the 8.2.1.
Select cast(VERSION as int) is bombing out because of those two values with a second . in them.
You may derive by using regexp_substr with \d pattern :
with tab as
(
select regexp_substr('8.2.1', '\d', 1, 1) from dual
union all
select regexp_substr('9.0.1', '\d', 1, 1) from dual
)
select * from tab;
For Oracle you must attend the value as string for retire only the part before the dot. Ex:
SELECT NVL( SUBSTR('8.2.1',0, INSTR('8.2.1','.')-1),'8.2.1') AS SR FROM DUAL;
Check than the value is repeated 3 times in the sentence, and if the value is zero or the value didn't have decimal part then it will return the value as was set.
I had to use T-SQL rather PL/SQL, but the idea is the same:
DECLARE #s VARCHAR(10);
SELECT #s='8.2.1';
SELECT CAST(LEFT(#s, CHARINDEX('.', #s) - 1) AS INT);
returns the integer 8 - note that it won't work if there are no dots because it takes the part of the string to the left of the first dot.
If my quick look at equivalent functions was correct, then in Oracle that would end up as:
SELECT CAST(SUBSTR(VERSION, 1, INSTR(VERSION, '.') - 1) AS INT)