I have a query of the form:
SELECT
col1,
col2,
(
SELECT my_value FROM my_second_table WHERE my_table.value = ...
) AS potentially_null_column
FROM my_first_table
When SELECT my_value FROM my_second_table WHERE my_table.value = ...
returns no rows, then potentially_null_column
is set to null
.
This jibes with the Postgres docs on Scalar Subqueries: https://www.postgresql.org/docs/8.3/sql-expressions.html#SQL-SYNTAX-SCALAR-SUBQUERIES:
But if, during a particular execution, the subquery returns no rows, there is no error; the scalar result is taken to be null.)
The problem is, I want potentially_null_column
to be a string 'UNSET'
instead of null
if there are no rows returned. Unfortunately, coalesce
won’t work here, since there are no rows returned to coalesce. How can I specify a non-null default value for a Scalar Subquery?
2
Answers
As said in comments, the
COALESCE
function is what you are looking for:SQL does not allow for mixed types to be returned in a single column, so if your data is not
VARCHAR
/TEXT
and similar, you are not allows to return a constant string instead ofNULL
.For instance, if your column is
INTEGER
/NUMERIC
, you can replaceNULL
by0
, not by'UNSET'
:Combine that with a
union
: demo at db<>fiddleIf you just move
coalesce()
to wrap the scalar subquery from the outside, it’ll work but it won’t care whether it doesn’t find a matching row at all, or if it does but withmy_value
set tonull
in it – in both cases it’ll report'UNSET'
just the same, obscuring potentially important information:UNION
can let you differentiate between these cases, so you can usecoalesce()
inside the scalar subquery if it’sFOUND UNSET
, while failover value inUNION
can give youNOT FOUND
. If it doesn’t matter or you intentionally wanted to merge the two cases, movingcoalesce()
up/out is enough.