I have this code as part of my code in snowflake:
Iff((Expr2)='pol',SumOfMANNLZD, '')
With Expr2= varchar column and SumOfMANNLZD=numeric column
When I run it, I have an error: Numeric value '' is not recognized.
But when I assigned '0' it works just fine. for example
Iff((Expr2)='pol',SumOfMANNLZD, '0')
However, I want it to return blank/null. Is there a way to archive this?
Thank you.
The IFF function's possible outputs should have same data type. SumOfMANNLZD is a numeric column, so Snowflake expects you to return a numeric column as the alternative output. If you are OK to return NULL values, you can put NULL instead of '':
with mydata as (
select 'pol' Expr2, 10 SumOfMANNLZD
union all
select 'dummy', 20
)
select Iff(Expr2='pol',SumOfMANNLZD, null) from mydata;
Or convert the SumOfMANNLZD to varchar if you want to return '':
with mydata as (
select 'pol' Expr2, 10 SumOfMANNLZD
union all
select 'dummy', 20
)
select Iff(Expr2='pol',SumOfMANNLZD::Varchar, '') from mydata;
in general if you want to compare a number to a string value you have to cast one or the other to the same type. make your numbers string or your strings to numbers. many languages have this ability. hopefully yours does.
Related
Hope this is right place to ask question related to snowflake database..
I would like to know how to replace string column value with 0 if it is null.
so far, i tried nvl function, but that didn't work.
CREATE TABLE EMP(ENAME VARCHAR(10));
INSERT INTO EMP VALUES('JACK');
INSERT INTO EMP VALUES(null);
SELECT NVL(ENAME,0) FROM EMP1;
Error :Numeric value 'JACK' is not recognized
Any help would be appreciated.
Thanks,
Nawaz
SQL is strongly typed. The output type of NVL is being inferred to be an NUMBER, so the actual query looks something like
SELECT NVL(ENAME::NUMBER, 0) FROM EMP1;
You should decide what type your output should be. If you want strings, then you will need to pass NVL a string, like
SELECT NVL(ENAME, '0') FROM EMP1;
If you want integers, you will need to convert the strings to integers safely. For example, if you want non-integers to become NULL, then 0, then you can use
SELECT NVL(TRY_TO_INTEGER(ENAME), 0) FROM EMP1;
I have observed an peculiar issue in the ISNUMERIC function. Below is the same code:
declare #variable nvarchar(max) = '123,456,789,147,258,369'
if (ISNUMERIC(#variable) = 1 )
select 'numeric' as output
else
select 'char' as output`
Below is the link for demo of the out put and different scenarios
Demo Here
It gives output as Character, though it numeric. Any suggestions for the behavior.
I have observed this behavior only when we copy the numbers and paste it in variable declaration, instead if we just type the number then it works fine.
Demo Here
Your CSV string is just that, a string, despite that it consists of CSV numbers. If you want to verify that you have an all-numeric CSV string you could try removing all commas and then asserting that what remains is a number:
declare #variable nvarchar(max) = '123,456,789,147,258,369'
if (ISNUMERIC(REPLACE(#variable, ',', ''l) = 1 )
select 'numeric' as output
else select 'char' as output
The string you defined, '123,456,789,147,258,369' is not a number, a number cannot have multiple commas.
If you have specific criteria on what do you consider a number, your should build your a user defined function to determine to sort strings as 'numeric' or 'char' according to your criteria.
Best regards,
Sergio
The reason for the behavior you are seeing appears to be due to the length of the string.
After reading this on MSDN:
ISNUMERIC returns 1 when the input expression evaluates to a valid
numeric data type
I ran some tests:
select ISNUMERIC('1,234')
1
select ISNUMERIC('1,234,456')
1
proves that you can have commas in the string
select isnumeric('123,456,789,147,258,369')
0
confirms the behavior you are seeing.
Your string is too big to be an int, but it could be a bigint, so:
select CONVERT(bigint,'123,456,789,147,258,369')
Error converting data type varchar to bigint.
select CONVERT(int,'1,234')
Conversion failed when converting the varchar value '1,234' to data type int.
proves that strings with commas can't be converted to int. What about decimals?
select CONVERT(decimal(10,0),'1,234')
Error converting data type varchar to numeric.
select CONVERT(float,'1,234')
Error converting data type varchar to float.
nope. that leaves money:
select CONVERT(money,'2,234')
2234.00
select CONVERT(money,'2,234,000')
2234000.00
so strings with (multiple) commas can be converted to money. But if the number would be too big to fit in a money datatype:
select CONVERT(money,'123,456,789,147,258,369')
Arithmetic overflow error converting expression to data type money.
then it can't be converted, and if it can't be converted, then ISNUMERIC()=0.
Thanks for your responses .Below is the final solution I got by eliminating the comma, NEXT line char and Space character as below:
declare #variable nvarchar(max) = '21386, 21385, 20178, 20176, 19958, 20026, 19976, 19933, 20029, 19921, 4552, 19784, 4700, 19730, 14655, 4749, 4998, 19604,'
if (ISNUMERIC(REPLACE( replace(REPLACE(REPLACE(#variable, ',' ,'1'), CHAR(10), ''), CHAR(9), ''), CHAR(13), '')) = 1 )
select 'numeric' as output
else select 'char' as output
I'm processing an audit log, and want to ignore entries where a NULL value is changed to zero (or remains NULL). The Old and New values are held in NVARCHAR fields regardless of the type of the fields being logged. In order to CAST a new value to decimal, to determine if it's zero, I need to restrict to cases where ISNUMERIC of the field returns 1.
I've got it to work with this strange bit of SQL - but feel sure there must be a better way.
WHERE MessageDesc LIKE 'poitem%'
AND NOT(OldValue IS NULL AND 0.0 =
CASE
WHEN ISNUMERIC(NewValue) = 1 THEN CAST(NewValue AS DECIMAL(18,4))
WHEN NewValue IS NULL THEN 0.0
ELSE 1.0
END)
Any suggestions?
SQL Server 2012 added a Try_Convert function, which returns NULL if the value cannot be casted as the given type. http://technet.microsoft.com/en-us/library/hh230993.aspx
WHERE NOT (OldValue is Null AND
(NewValue is null OR try_convert(float, NewValue) = 0.0)
)
If using a version prior to 2012, check out Damien_The_Unbeliever's answer here: Check if a varchar is a number (TSQL) ...based on Aaron's comment this will not work in all cases.
Since you are using SQL 2008, then it appears a combination of isnumeric and a modified version of Damien's answer from the link above will work. Your current solution in your question would have problems with values like '.', '-', currency symbols ($, etc.), and scientific notation like '1e4'.
Try this for SQL 2008 (here is SQLFiddle with test cases: http://sqlfiddle.com/#!3/fc838/3 ): Note: this solution will not convert text values to numeric if the text has commas (ex: 1,000) or accounting notation with parens (ex: using "(1)" to represent "-1"), because SQL Server will throw an error when trying to cast to decimal.
WHERE t.OldValue is null
AND
(
t.NewValue is null
OR
0.0 =
case
when isnumeric(t.NewValue) = 1
--Contains only characters that are numeric, negative sign, or decimal place.
--This is b/c isnumeric will return true for currency symbols, scientific notation, or '.'
and not (t.NewValue like '%[^0-9.\-\+]%' escape '\')
--Not other single char values where isnumeric returns true.
and t.NewValue not in ( '.', '-', '+')
then cast(t.NewValue as decimal(18,4))
else null --can't convert to a decimal type
end
)
Avoid ISNUMERIC() since it is problematic with '.'.
-- Dot comes up as valid numeric
select
ISNUMERIC('.') as test1,
ISNUMERIC('1A') as test2,
ISNUMERIC('1') as test3,
ISNUMERIC('A1') as test4
-- Results window (text)
test1 test2 test3 test4
----------- ----------- ----------- -----------
1 0 1 0
Use COALESCE() instead.
WHERE MessageDesc LIKE 'poitem%'
AND
NOT (OldValue IS NULL AND
CAST(COALESCE(NewValue, '0') AS DECIMAL(18,4)) = 0)
I have a temporary table I'm using for parsing, #rp.
#rp contains an nvarchar(max) column, #rp.col8, which holds positive and negative numbers to two decimal places of precision e.g. `1234.26'.
I'm able to run the following query and get out a set of converted values out:
select * from
(
select CONVERT(decimal(18,2),rp.col8) as PARSEAMT
from #rp
where
--#rp filtering criteria
)q
However, when I try to query for PARSEAMT = 0 in the following manner, I get the standard '8114, Error converting data type varchar to numeric.':
select * from
(
select CONVERT(decimal(18,2),col8) as PARSEAMT
from #rp
where
--#rp filtering criteria
)q
where q.PARSEAMT = 0
Without that where clause, the query runs fine and generates the expected values.
I've also tried other clauses like where q.PARSEAMT = 0.00 and where q.PARSEAMT = convert(decimal(18,2),0).
What am I doing wrong in my comparison?
I was going to suggest you select PARSEAMT into another temp-table/table-variable but I can see you've already done that from your comments.
Out of interest what does the following yield?
select
col8
from
#rp
where
-- ISNUMERIC returns 1 when the input expression evaluates to a valid
-- numeric data type; otherwise it returns 0. Valid numeric data types
-- include the following:
isnumeric(col8) <> 1
I am working with a table that comes from an external source, and cannot be "cleaned". There is a column which an nvarchar(20) and contains an integer about 95% of the time, but occasionally contains an alpha. I want to use something like
select * from sch.tbl order by cast(shouldBeANumber as integer)
but this throws an error on the odd "3A" or "D" or "SUPERCEDED" value.
Is there a way to say "sort it like a number if you can, otherwise just sort by string"? I know there is some sloppiness in that statement, but that is basically what I want.
Lets say for example the values were
7,1,5A,SUPERCEDED,2,5,SECTION
I would be happy if these were sorted in any of the following ways (because I really only need to work with the numeric ones)
1,2,5,7,5A,SECTION,SUPERCEDED
1,2,5,5A,7,SECTION,SUPERCEDED
SECTION,SUPERCEDED,1,2,5,5A,7
5A,SECTION,SUPERCEDED,1,2,5,7
I really only need to work with the
numeric ones
this will give you only the numeric ones, sorted properly:
SELECT
*
FROM YourTable
WHERE ISNUMERIC(YourColumn)=1
ORDER BY YourColumn
select
*
from
sch.tbl
order by
case isnumeric(shouldBeANumber)
when 1 then cast(shouldBeANumber as integer)
else 0
end
Provided that your numbers are not more than 100 characters long:
WITH chars AS
(
SELECT 1 AS c
UNION ALL
SELECT c + 1
FROM chars
WHERE c <= 99
),
rows AS
(
SELECT '1,2,5,7,5A,SECTION,SUPERCEDED' AS mynum
UNION ALL
SELECT '1,2,5,5A,7,SECTION,SUPERCEDED'
UNION ALL
SELECT 'SECTION,SUPERCEDED,1,2,5,5A,7'
UNION ALL
SELECT '5A,SECTION,SUPERCEDED,1,2,5,7'
)
SELECT rows.*
FROM rows
ORDER BY
(
SELECT SUBSTRING(mynum, c, 1) AS [text()]
FROM chars
WHERE SUBSTRING(mynum, c, 1) BETWEEN '0' AND '9'
FOR XML PATH('')
) DESC
SELECT
(CASE ISNUMERIC(shouldBeANumber)
WHEN 1 THEN
RIGHT(CONCAT('00000000',shouldBeANumber), 8)
ELSE
shouoldBeANumber) AS stringSortSafeAlpha
ORDEER BY
stringSortSafeAlpha
This will add leading zeros to all shouldBeANumber values that truly are numbers and leave all remaining values alone. This way, when you sort, you can use an alpha sort but still get the correct values (with an alpha sort, "100" would be less than "50", but if you change "50" to "050", it works fine). Note, for this example, I added 8 leading zeros, but you only need enough leading zeros to cover the largest possible integer in your column.