Oracle case statement not returning values for no row results - sql

I have a simple case statement as follows:
select
case WHEN upper(VALUE) is null then 'A_VALUE_ANYWAY' end test
FROM
V$SYSTEM_PARAMETER
WHERE
UPPER(VALUE)= 'NO_VALUE_IS_HERE'
This code is designed to return 'A_VALUE_ANYWAY' because there is no output from the SQL.
However, it does not return anything at all.
Essentially, what I would like is a value being forced to return from the case statement instead of just no rows.
Am I able to do that with the case statement? Is there some form of no data found handler I should be using instead?
I have examined this similar question but this is very complex and does not seem possible with this more simple statement
SQL CASE Statement for no data
Also, this, which uses a union to get a value from dual:
Select Case, when no data return
Which seems like a "Fudge" I feel like there must be some designed way to handle no data being found in a case statement.

From Oracle 12, you can use the FETCH syntax so that you do not have to query the table multiple times:
SELECT value
FROM (
SELECT value,
1 AS priority
FROM V$SYSTEM_PARAMETER
WHERE UPPER(VALUE)= 'NO_VALUE_IS_HERE'
UNION ALL
SELECT 'A_VALUE_ANYWAY',
2
FROM DUAL
ORDER BY priority
FETCH FIRST ROW WITH TIES
)
db<>fiddle here

What you are asking is: "if my query returns no rows, I want to see a value". That cannot be solved with a case expression. A case expression transforms the results of your query. If there are no results, nothing can be transformed. Instead you could could modify your query and union it with another select from dual that returns a string if the query itself returns no results. That way either part of the UNION ALL will return something.
SELECT
VALUE
FROM
V$SYSTEM_PARAMETER
WHERE
UPPER(VALUE)= 'NO_VALUE_IS_HERE'
UNION ALL
SELECT 'A_VALUE_ANYWAY'
FROM
DUAL
WHERE NOT EXISTS (SELECT 1
FROM
V$SYSTEM_PARAMETER
WHERE UPPER(VALUE)= 'NO_VALUE_IS_HERE'
This is the same technique as in the SQL Case statement for no data question.

Related

Counter-intuitive behavior of SUM( ) of UNION in Sqlite3

I ran this code in an sqlite3 terminal (version 3.29.0), and the result is a little strange:
sqlite> select sum((select 4 union all select 2 ));
4
sqlite> select sum((select 4 union select 2 ));
2
I understand why union reverses the table, but why does sum choose the first element?
Meanwhile, this code works just as expected:
sqlite> select sum(x) from (select 4 as x union all select 2 as x);
6
Is this the intended behavior, or is this a bug in sqlite? And if it's intended, what's the logic (and semantics) behind it?
That's expected behavior.
From the documentation (emphasis added)
A SELECT statement enclosed in parentheses is a subquery. All types of SELECT statement, including aggregate and compound SELECT queries (queries with keywords like UNION or EXCEPT) are allowed as scalar subqueries. The value of a subquery expression is the first row of the result from the enclosed SELECT statement. The value of a subquery expression is NULL if the enclosed SELECT statement returns no rows.
The UNION example just happened to end up returning.rows in a different order than the UNION ALL one. Without an ORDER BY neither one is guaranteed to use a particular order, though.

SQL UNION vs OR, INTERSECT vs AND

I would like to know what the difference between an INTERSECT and an AND statement as well as a UNION statement and a OR statement is.
Is there a specific scenario where either one is recommended to use and can could I always use a OR/AND instead of an UNION/ INTERSECT ?
Use AND or OR between terms in a WHERE clause. If the complete boolean expression evaluates as true, then the row is included in the query's result set.
WHERE country = 'Canada' AND age > 21
Use INTERSECT or UNION between SELECT queries. If a row appears in both result sets, or either result set, respectively, then the row is included in the compound query's result set.
SELECT customer_id FROM archived_orders
UNION
SELECT customer_id FROM recent_orders

Get count and result from SQL query in Go

I'm running a pretty straightforward query using the database/sql and lib/pq (postgres) packages and I want to toss the results of some of the fields into a slice, but I need to know how big to make the slice.
The only solution I can find is to do another query that is just SELECT COUNT(*) FROM tableName;.
Is there a way to both get the result of the query AND the count of returned rows in one query?
Conceptually, the problem is that the database cursor may not be enumerated to the end so the database does not really know how many records you will get before you actually read all of them. The only way to count (in general case) is to go through all the records in the resultset.
But practically, you can enforce it to do so by using subqueries like
select *, (select count(*) from table) from table
and just ignore the second column for records other than first. But it is very rude and I do not recommend doing so.
Not sure if this is what you are asking for but you can call the ##Rowcount function to return the count of the previous select statement that has been executed.
SELECT mytable.mycol FROM mytable WHERE mytable.foo = 'bar'
SELECT ##Rowcount
If you want the row count included in your result set you can use the the OVER clause (MSDN)
SELECT mytable.mycol, count(*) OVER(PARTITION BY mytable.foo) AS 'Count' FROM mytable WHERE mytable.foo = 'bar'
You could also perhaps just separate two SQL statements with the a ; . This would return a result set of both statements executed.
You would used count(*)
SELECT count(distinct last)
FROM (XYZTable)
WHERE date(FROM_UNIXTIME(time)) >= '2013-10-28' AND
id = 90 ;

SQL returning custom values based on query results keeping performance in mind

I need help on performance of a query I have that is very slow.
The query is doing a case on a column in order to return a different text value
based on the number.
If I had a table with values 1-5 and 8-10 If something has a value of 1 it should display 'Apple' or if it is 2 it must display 'pear' if it is anything other than 1-5 then it is 'other'. Currently a case statement is being used, but I heard that functions on a query makes it slower.
All I want is the 'Wording' to appear instead of the the number but because the table is so big it feels to me like it is iterating each row just to determine what to display.
Is there a faster way of doing this.I considered doing a join, which seems like it would work nice, but I dont know how to write 'other' for anything other than 1-5
A case statement is not a function. User-defined functions do have additional overhead in some versions of SQL. You don't, as a general rule, need to worry about the overhead for built-in functions.
You could do this with a join as:
with lookup as (
select 1 as val, 'Apple' as str union all
select 2 as val, 'Pear' as str union all
select 3 union all select 4 union all select 5
)
select coalesce(l.val, 'other')
from t left outer join
lookup l
on t.col = l.val
I would expect the case statement to be marginally faster though.

Enter multiple rows explicitly in single select statement

I am testing a query and want to use SELECT to get some initial data like so:
SELECT 1,2,3
UNION
SELECT 2,3,4
Is there a syntax to fold these two selects into one or do I have to use a UNION statement for each row?
You can use values clause
select t.* from (values(1,2,3), (2,3,4)) as t(col1,col2,col3)
If you want to display the result as one result set then you have to use union/union all