I suppose, what you are actually trying to do should look like this:
SELECT COALESCE((
SELECT now() - min(AcctStartTime)
FROM radacct
WHERE userName = 'test156'), interval '0s')
If the sub-select (with the alias elapsed_time_from_first_login
) does not find a row, it will return a NULL value, but no row.
To catch this you would wrap the whole sub-select
in a COALESCE
statement - which is simpler than CASE
for the purpose.
I overlooked the aggregate function min()
at first which converts "no row" to NULL
. So, as long as you have an aggregate function in the subselect, the simple form below does the trick just as well. Here is a quick demo on sqlfiddle to show the effect.
Other problems with your query have already been pointed out. But this is the much simpler solution. It returns an interval
rather than an integer
.
Convert to integer
Simplified, after comments by @artaxerxe.
Simple form does the job without check for "no row":
SELECT COALESCE(EXTRACT(epoch FROM now() - min(AcctStartTime))::int, 0)
FROM radacct
WHERE userName = 'test156';
Details about EXTRACT(epoch FROM INTERVAL)
in the manual.
Aggregate functions and NULL
One more remark: If you had used the aggregate function count()
- not sum()
as you had in your question initially - the outcome would be different. count()
is a special case among the standard aggregate functions in that it never returns NULL
. If no value (or row) is found, it returns 0
instead.
This excerpt from the manual on aggregate functions seems to cover it pretty much:
It should be noted that except for count, these functions return a
null value when no rows are selected. In particular, sum of no rows
returns null, not zero as one might expect, and array_agg returns null
rather than an empty array when there are no input rows. The coalesce
function can be used to substitute zero or an empty array for null
when necessary.