REPLACE WITH NVL - sql

select to_number(replace(nvl('-100,000',0),'',','),'999,999,999.99')from dual;
... produces the output: 100000
Now I use the same expression in my procedure with table column:
select to_number(replace(nvl(TABLEA.VOLUME,0),'',','),'999,999,999.99')from TABLEA;
... and get the output: INVALID NUMBER
Column VOLUME in TABLEA is of type VARCHAR2.

Most certainly the contents of column VOLUME are stored as strings without the grouping character ( , ). Thus the strings violate the format in the conversion with to_number.
In addition, the argument order in REPLACE makes no sense.
Finally, you want to swap the calls to NVL and REPLACE.
So - assuming that you want to parse numbers with 2 fractional digits given as strings - use the following:
select to_number ( nvl ( replace (TABLEA.VOLUME, ',', ''), 0), '999999999.99') from TABLEA;

Seems you want to convert the string values to money format.
First, consider replace as you did by switching '' and ',' parameters in the argument order to remove the commas, and making suitable for numeric conversion as :
to_number(replace(nvl(str,0),',','')),
and then apply the money format as :
with tableA as
(
select '-100,000' as volume
from dual
)
select to_char(
to_number(replace(nvl(volume,0),',',''))
,'fm999G999G990D00','NLS_NUMERIC_CHARACTERS = ''.,''')
as Money
from tableA;
MONEY
-----------
-100,000.00
Depending on the currency displaying style the order of dot and comma can be switched as
'NLS_NUMERIC_CHARACTERS = '',.''' to display the money as -100.000,00.
P.S. first of all, you need to make sure all the data for volume column can be casted to number to be able to use to_number() conversion.
Demo

Related

Filtering a data set on dates with a weird format

I have a column populated by dates in the format that follows...
purch_dt
8/18/2014
9/27/2014
1/3/2015
10/29/2016
11/5/2016
2/9/2017
3/1/2017
6/29/2017
12/27/2017
2/25/2018
I'm wanting to filter the data set to only contain dates within a certain range, but when I try to code WHERE purch_dt BETWEEN '3/1/2017' AND '6/29/2017' I get the error that says "A character string failed conversion to a numeric value." Any idea how to fix this?
Not 100% sure of this one, but at least wanted to help. I think if you cast the column appropriately it should work, as in:
select *
from my_table
where cast(purch_dt as TIMESTAMP(0) format 'd/m/yyyy')
between date '2017-03-01' AND date '2017-06-29'
In any case, I would strongly suggest storing dates as DATE and not VARCHAR. Storing them as VARCHAR is just asking for trouble.
To my knowledge, there is no format or cast in Teradata that will accept single digit months and days. So you'll have to parse this ugly string and rebuild it as a date.
STRTOK will split on the \ delimiter for you, and lpad gets you your leading 0s where you need them.
create volatile table vt_NotADate
(not_date varchar(10))
on commit preserve rows;
insert into vt_notadate values ('12/27/2017');
insert into vt_notadate values ('9/1/2017');
select
not_date,
cast(lpad(strtok(not_date,'/',1),2,'0') as char(2)) as m,
cast(lpad(strtok(not_date,'/',2),2,'0') as char(2)) as d,
strtok(not_date,'/',3) as y,
cast (y || '-' || m || '-' || d as date) as a_date
from
vt_notadate

Oracle SQL TO_CHAR Function return values

I don't understand why these two code results are identically the same? I thought if I have quotes it just concatenate strings. Why not first one is 300.5100? I know second one is 400.5 anyway. Thank you
Select to_char('300.5' + '100') From Dual;
Select to_char(300.5 + 100) From Dual;
To concatenate strings in SQL you have to use ||. The + is only there to add numbers. If you didn't pass '300.5' + '100' you would simply get an error, e.g. the following is invalid SQL:
select '300.5' + '100'
from dual;
But as to_char() expects a number as the input parameter Oracle implicitly converts those strings to numbers and then adds them, just like in the second statement.
concatenation is
'xxx' || 'yyy'
your example allows the literals to be converted to numeric then treated as normal numbers.

Leading Zeros getting truncated using SUBSTRING

One of the values in the column is
089-002007
I wish to extract all the numbers after '-'
SELECT SUBSTR(EMP_NO,5)
FROM Table_Name
However, I get the output as '2007', the leading zeros got truncated. I have multiple values where it starts with 0 after the '-'.
how can I fix this?
Looks like it's implicitly changing the result to int, hence chopping off leading zeroes. I would suggest CAST-ing the SELECT
SELECT CAST(SUBSTR(EMP_NO,5) AS VARCHAR(10))
FROM Table_Name
What platform and version of DB2?
You should be getting '002007' back given the code you've shown.
The output of SUBSTR() is already varchar.
The DBMS wouldn't change it from varchar to int, unless you've tried to treat it like an int.
select substr('089-002007',5)
from sysibm.sysdummy1
Returns
SUBSTR
002007
On the other hand,
select substr('089-002007',5) + 0
from sysibm.sysdummy1
Returns
Numeric Expression
2,007

Why does my dynamic to_char not work?

I want to return a list of results with the following WHERE clause:
SELECT ...
FROM XTABLE
WHERE MMONTH = to_char(to_date('03/2013','mm/yyyy'),'mm')
AND MYEAR = to_char(to_date('03/2013','mm/yyyy'),'yyyy')
where MMONTH is a column of type CHAR(3 Bytes) and MYEAR is a column of type CHAR(4 Bytes).
Why doesn't it work compared to
SELECT ...
FROM XTABLE
WHERE TO_DATE(MMONTH,'MM') = to_date(to_char(to_date('03/2012','mm/yyyy'),'mm'),'mm')
AND TO_DATE(MYEAR,'yyyy') = to_date(to_char(to_date('03/2012','mm/yyyy'),'yyyy'),'yyyy')
I am reluctant to change the format of the date ('03/2012') on the right as I have additional queries that use the same date, so I thought using just one type of date would be good.
From the Oracle documentation,
The CHAR data type specifies a fixed-length character string. Oracle ensures that all values stored in a CHAR column have the length specified by size. If you insert a value that is shorter than the column length, then Oracle blank-pads the value to column length.
So, if you insert '03' into MMONTH column, it will have a space at the end. The output of to_char function will return simply '03' without any space. Hence, when you compare it won't match.
Recommended way, is to change the datatype of your columns to VARCHAR2. You can also change the column size of MMONTH to 2.
Following on from Ramblin' Man's explanation of the problem, if you really can't change the data type, you could use where trim(mmonth) = which has index implications, or apply rpad or or cast to your to_char. SQL Fiddle of all three options, but personally I'd go for the cast as that's most self-explanatory:
SELECT ...
FROM XTABLE
WHERE MMONTH = cast(to_char(to_date('03/2013','mm/yyyy'),'mm') as char(3))
AND MYEAR = to_char(to_date('03/2013','mm/yyyy'),'yyyy');

Conversion of varchar to number

I have a question that bothers me. How can i convert a varchar to number when inside the varchar value consists of alphabets.
For my varchar price column values:
14dollars10cents
15dollars20cents
By converting it to varchar to number price column, the values should be:
1410
1520
I know that if the varchar does not consists any alphabets, it can auto convert by"
SELECT CONVERT(INT, PRICE) FROM Table
Is there any way to get rid of the alphabets in the middle as I would like to do mathematical function on it.
Updated attempt of putting fixed point number in:
SELECT CAST (Replace(REPLACE(PRICE, 'dollars', '.'),'cents','') AS Number(4,2)))
FROM TEST;
Thanks
You could just use REGEXP_REPLACE to remove all non digit characters:
SELECT REGEXP_REPLACE(price, '[^[:digit:]]')
FROM table;
To then convert this to a number:
SELECT TO_NUMBER(REGEXP_REPLACE(price, '[^[:digit:]]'))
FROM table;
If you want to add the point in then you can do that with REGEXP_REPLACE too:
SELECT TO_NUMBER(REGEXP_REPLACE(val, '^([0-9]*)([^[:digit:]]*)([0-9]*)(.*)$', '\1.\3'))
FROM table;
Voila...
SELECT CAST(REPLACE(YourVarcharCol, 'dollars', '') AS INT) FROM Table
The issue with this is it will break if the varchar still contains alpha-numeric characters.
How about using translate to strip out the unwanted characters.
SELECT TO_NUMBER(TRANSLATE('14dollars10cents','1234567890dolarscents','1234567890')) FROM DUAL
No I don't think there is direct way.
you can do string parsing to get your integer value.