Is it possible to use a COALESCE function inside a SUM function? - sql

I'm trying to use COALESCE function at postgres in a query like this:
SELECT
id_school,
SUM(COALESCE((student->'name'->>'age'), '0')::numeric)
FROM
teachers
GROUP BY 1;
The problem is at line:
SUM(COALESCE((student->'name'->>'age'), '0')::numeric)
I tried to use COALESCE because I'm receiving some empty strings and the ERROR: invalid input syntax for type numeric: ""
Shouldn't COALESCE solve this casting error? Can't I use COALESCE in a SUM function?

You don't actually need the coalesce() function inside the sum, because sum will ignore NULL values anyway.
You error isn't caused by a NULL value, but by an empty string.
So you need to convert the empty string to a NULL value. This can be done using nullif() in Postgres
SELECT id_school,
SUM(nullif(student->'name'->>'age'), '')::numeric)
FROM teachers
GROUP BY 1;
If you could also have strings with blanks in it the JSON value, you might want to consider nullif(trim(student->'name'->>'age'), '')

COALESCE returns first non-null argument. Empty string is non-null. You are trying to cast '' to numeric value.
You can use NULLIF to get null instead of empty string in COALESCE.
SQL Coalesce with empty string

Related

nvl function not returning expected result

I know that nvl function works only for 'null', not empty string. I just wanted to know if there was a function that helps me replace blank/null values with another one.
I used instead:
CASE WHEN expression_1 is null or expression_1 = '' then expression_2 else expression_1
expression_1 column has empty cells, not null cells.
NVL() is a function most typically associated with Oracle. The equivalent standard SQL function is COALESCE().
By default, Oracle treats NULL strings and empty strings ('') as the same. So, '' IS NULL evaluates to "true" (and '' = '' rather confusingly evaluates to NULL, which is false in a WHERE clause).
So, you can use NVL() or COALESCE() on an empty string. These are the same:
NVL(NULL, 'A')
NVL('', 'A')
COALESCE(NULL, 'A')
COALESCE('', 'A')
Here is a db<>fiddle.
Incase the column contains blank spaces, you can use TRIM() besides NVL() so as you can gracefully remove blank spaces before you apply NVL().
NVL(TRIM(' '),'X') --> returns X
db<>fiddle -
https://dbfiddle.uk/?rdbms=oracle_18&fiddle=08435972cbfb799329e6609349c70a04
I believe you are looking Coalesce ():
coalesce(expression2, expression1)
Brings the first non-null value from expression2 else expression 1. If all expressions evaluate to null, then the COALESCE function will return null.
NVL function lets you substitute a value when a null value is encountered:
nvl(expression2, expression1)
Sql statement would replace expression 2 with with expression 1 if it finds null value in there.
Difference: NVL always evaluates both arguments, while COALESCE usually stops evaluation whenever it finds the first non-NULL
One awesome explanation given by #Quassnoi here

Why does null||null return a null value but concat(null,null) returns an empty string in postgres? [duplicate]

This question already has answers here:
String concatenation with a null seems to nullify the entire string - is that desired behavior in Postgres?
(4 answers)
Closed 1 year ago.
I'm trying to understand the differences between concat() and || in postgres when using nulls. Why does concat() return an empty string if both sides of the concat are null?
Take this query For Example:
SELECT concat(NULL,NULL) AS null_concat, NULL||NULL AS null_pipes,
concat(NULL,NULL) IS NULL is_concat_null, NULL||NULL IS NULL is_pipe_null
will return:
I understand that concat() ignores nulls but if all the values in the concat are null, wouldn't the expected result be a null? Is this typical behavior of all functions in postgres? I couldn't find anything in the documentaion around this scenario.
Edit:
I had a thought that maybe this was the expected result of any string function but that does not appear to be the case. Both upper() and left() return nulls if a null value is passed:
SELECT concat(NULL), NULL||NULL, UPPER(null), left(NULL,1)
Result:
in concat() function:
text concat(str "any",...) Concatenate all arguments. NULL arguments are ignored.
Note: NULL arguments are ignored.
Imagine this:
The input arguments concat() are dynamical.
So when we write: concat('a',null,null,null,null) => we have written: concat('a')
(As opposed to the || operator that NULL destroyed everything)
in || operator:
the string concatenation operator (||) still accepts non-string input,
so long as at least one input is of a string type
So NULL||NULL has a wrong syntax
But why not give Error?
Because in the concat operation, if we do not reject the NULL (Like the concat function), they will overwhelm everything
SELECT NULL ||'aaa'||'bbb'||'ccc'||'ddd'
output:
NULL
more info:
Note: Before PostgreSQL 8.3, these functions would silently accept
values of several non-string data types as well, due to the presence
of implicit coercions from those data types to text. Those coercions
have been removed because they frequently caused surprising behaviors.
However, the string concatenation operator (||) still accepts
non-string input, so long as at least one input is of a string type,
as shown in Table 9-6. For other cases, insert an explicit coercion to
text if you need to duplicate the previous behavior.

Hive - how to check if a numeric columns have number/decimal?

I am trying to generate a hive query which will take multiple numeric column names and check whether it is has numeric values. If the column has numeric values then the output should be (column name,true) else if the field has NULL or some string value the output should be (column name,false)
SELECT distinct (test_nr1,test_nr2) FROM test.abc WHERE (test_nr1,test_nr2) not like '%[^0-9]%';
SELECT distinct test_nr1,test_nr2 from test.abc limit 2;
test_nr1 test_nr2
NULL 81432269
NULL 88868060
the desired output should be :
test_nr1 false
test_nr2 true
Since test_nr1 is a decimal field and it has NULL values, it should output false.
Appreciate valuable suggestions.
You can use cast function. It returns NULL when the value can not not be cast to numeric.
For example:
select case when cast('23ccc' as double) is null then false else true end as IsNumber;
You're trying to use character class pattern matching syntax here, and it doesn't work in every SQL implementation IIRC, however, regexp matching works in most, if not all, SQL implementations.
Considering you're using hive, this should do it:
SELECT ('test_nr1', test_nr1 RLIKE '\d'), ('test_nr2', test_nr2 RLIKE '\d') FROM test.abc;
You should remember that regexp matching is very slow in SQL though.

Oracle DECODE not working

I have an oracle decode that is checking if a value is NULL before updating the decimal precision. The problem is when the value in the price_precision column isn't null the decode still goes to the d.price value, but it should go to the default value. Here is the line of code for the decode:
DECODE(d.PRICE_PRECISION, NULL, d.price,TO_CHAR(DECODE(d.price,NULL, '', d.price), CONCAT('9999990',RPAD('D', d.PRICE_PRECISION+1,'9')))) price
I know for a fact there is non-NULL data in the Price _Precision column, because I can see it in the return for the select statement. Is there something wrong with my decode? any ideas why the decode isn't going to the default statement?
It seems implicit conversion took place. Consider this
DECODE(d.PRICE_PRECISION, NULL, to_char(d.price), TO_CHAR....
From Oracle docs:
Oracle automatically converts expr and each search value to the
datatype of the first search value before comparing. Oracle
automatically converts the return value to the same datatype as the
first result.
For Null values, use NVL function.
select nvl(name,'not registered') from table;
When name is null values, return 'not registered'.
You can use this together with DECODE function.
decode(nvl(PRICE,'Not valid'),'Not valid',0,PRICE)
In calculations, this avoids problems.
From Oracle docs:

Select ISNULL is not returning replacement value

ContactPerson type is nvarchar.
The issue is when ContactPerson is empty not returning n/a
Query
Select ISNULL(ContactPerson,'n/a') from [dbo].[Suppliers]
An empty string ('') and not the same thing as a null value. ISNULL() returns the replacement value only for an actual null value.
You can use NULLIF() to evaluate an empty string into a null value:
SELECT ISNULL(NULLIF(ContactPerson, ''), 'n/a') ...
I would suggest to use COALESCE instead of ISNULL, with NULLIF function:
SELECT COALESCE(NULLIF(ContactPerson,''),'n/a')
FROM [dbo].[Suppliers]
You can find the difference of COALESCE and ISNULL f.e. here.