Returning a default value when query does not return rows in DB2 - sql

For a query I am using, a default value will need to be returned if no rows are returned (since the output will be used downstream). The problem I'm encountering is how to programmatically identify that zero or null rows are returned so that the query knows to use the 'default' value.
SELECT DISTINCT fieldName from DB2Table
WHERE qualifier1 = '___'
AND qualifier2 = '___';
This can return either a value or nothing (as in, no rows at all). I've attempted using count(*), NOT NULL, and EXISTS() within a CASE Statement, but I've had no luck.
**Psuedocode**:
IF query returns values, return those
ELSE return "Some Value"
Any tips/insights would be greatly appreciated!

If the query doesn't return a row and a default value needs to be returned in that case, use
SELECT
COALESCE(
(SELECT DISTINCT fieldName from DB2Table
WHERE qualifier1 = '___' AND qualifier2 = '___'), 'DEFAULTVALUE'
)
FROM sysibm.sysdummy1

If you are only expecting one row, then use aggregation:
SELECT COALESCE(fieldName, 'DEFAULT VALUE')
FROM DB2Table
WHERE qualifier1 = '___' AND qualifier2 = '___';
If you could be getting multiple rows, then here is another method:
WITH t as (
SELECT fieldName
FROM DB2Table
WHERE qualifier1 = '___' AND qualifier2 = '___'
)
SELECT t.*
FROM t
UNION ALL
SELECT 'DEFAULT VALUE'
FROM sysibm.sysdummy1
WHERE NOT EXISTS (SELECT 1 FROM t);

Related

Conditional statements in "WHERE" in SQL Server

What I want to achieve is to have a switch case in the where clause. I want to test if this statement returns something, if it returns null, use this instead.
Sample:
SELECT [THIS_COLUMN]
FROM [THIS_TABLE]
WHERE (IF THIS [ID] RETURNS NULL THEN DO THIS SUBQUERY)
What I mean is that it will do this query first.
SELECT [THIS_COLUMN]
FROM [THIS_TABLE]
WHERE [ID] = 'SOMETHING'
If this returns NULL, do this query instead:
SELECT [THIS_COLUMN]
FROM [THIS_TABLE]
WHERE ID = (SELECT [SOMETHING] FROM [OTHER_TABLE]
WHERE [SOMETHING_SPECIFIC] = 'SOMETHING SPECIFIC')
Note that the expected results from the intended query varies from 30 rows up to 15k rows. Hope it helps.
Adding more information:
The results for this query will be used for another query but will just focus on this query.
Providing a real case scenario:
[THIS_COLUMN] is expected to have a list of VALUES.
[THIS_TABLE] contains the latest data only(let's say 1 year's worth of data) while the [OTHER_TABLE] contains the historical data.
What I want to achieve is when I query for a data that is not with in the 1 year's worth of data, IE 'SOMETHING' is not with in the 1 year scope(or in my case it returns NULL), I will use the other query where I query the 'SOMETHING_SPECIFIC'(Or may be 'SOMETHING' from the first statement makes more sense) from the historical table.
If I as reading through the lines correctly, this might work:
SELECT THIS_COLUMN
FROM dbo.THIS_TABLE TT
WHERE TT.ID = 'SOMETHING'
OR TT.ID = (SELECT OT.SOMETHING
FROM dbo.OTHER_TABLE OT
WHERE OT.SOMETHING_SPECIFIC = 'SOMETHING SPECIFIC'
AND NOT EXISTS (SELECT 1
FROM dbo.THIS_TABLE sq
WHERE sq.ID = 'SOMETHING'
AND THIS_COLUMN IS NOT NULL))
Note, however, that this could easily not be particularly performant.
You an use union all and not exists:
select this_column
from this_table
where id = 'something'
union all
select this_column
from this_table
where
not exists (select this_column from this_table where id = 'something')
and id = (select something from other_table where something_specific = 'something specific')
The first union member attempts to find rows that match the first condition, while the other one uses the subquery - the not exists prevents the second member to return something if the first member found a match.
90% of the time you can use a query-batch (i.e. a sequence of T-SQL statements) in a single SqlCommand object or SQL Server client session, so with that in-mind you could do this:
DECLARE #foo nvarchar(50) = (
SELECT
[THIS_COLUMN]
FROM
[THIS_TABLE]
WHERE
[ID] = 'SOMETHING'
);
IF #foo IS NULL
BEGIN
SELECT
[THIS_COLUMN]
FROM
[THIS_TABLE]
WHERE
[ID] = (
SELECT
[SOMETHING]
FROM
[OTHER_TABLE]
WHERE
[SOMETHING_SPECIFIC] = 'SOMETHING SPECIFIC'
)
END
ELSE
BEGIN
SELECT #foo AS [THIS_COLUMN];
END
That said, SELECT ... FROM ... WHERE x IN ( SELECT y FROM ... ) is a code-smell in a query - you probably need to rethink your solution entirely.

SQL Select empty

I have the following code in Oracle 11:
select xmlelement("foo", xmlagg(xmlelement("bar",myValues))) from someTable where rownum = 0; --Changing the rownum from 0 should give me values
The output currently is: <foo></foo>
I would instead like this to return nothing, or null, when no rows are select. Otherwise it'll be a XMLtype with the aggregated data like how I have it above.
How would I be able to achieve this for the case when no rows are selected?
You can use case select:
select case when count (*) != 0 then xmlelement("foo", xmlagg(xmlelement("bar",myValues))) end
You can convert to CLOB using getClobval function and do a comparison.
SELECT
xml
FROM
(
SELECT
xmlelement("foo",xmlagg(xmlelement("bar",myvalues) ) ).getclobval() xml
FROM
sometable
)
WHERE
TO_CHAR(xml) != '<foo></foo>';

NVL Column and NULL

I have rows as shown below
ProductId ProductName ProductDesc ProductLoc
101 Camel Pencil B-10
102 Parker Pen
103 Mirado Pen C-10
When I execute the following SQL query
SELECT *
FROM tablename
WHERE productloc = NVL ('', productloc)
It gives me the 1st and 3rd row, what I would like to achieve is if productloc is null in where condition of the SQL, then I should get all three rows.
How can I get the desired output.
select * from tablename;
Is what you need in that case because your where gives no effect. You compare column with itself.
If you want to filter and include nulls you can do (but probably replace one productloc with some value:
select * from tablename where productloc = productloc or productloc is null;
Or:
select * from tablename where nvl(productloc, 'SOME_UNIQUE_VAL') = nvl(productloc, 'SOME_UNIQUE_VAL');
and also replace one of productloc by some value.
Try something like :
SELECT *
FROM tablename
WHERE nvl(productloc,'zzz') = (case when productloc is null then 'zzz' else productloc end )
Here zzz is some dummy value, which otherwise should not be present as value in particular column.
I suppose three different solutions:
If you want all rows (with productloc null and valued) you can write the following query:
SELECT *
FROM tablename
Without WHERE clause.
If you want extract all rows with productloc has a specified value or is null, so you can write the following query:
SELECT *
FROM tablename
WHERE productloc IS NULL OR productloc = YOURVARIABLE
or (the last, without use OR condition)
SELECT *
FROM tablename
WHERE NVL(productloc, YOURVARIABLE) = YOURVARIABLE
I assume you are using Oracle. In Oracle "NULL" is not a value and because of it any compare function will return false.
I recomend:
SELECT *
FROM tablename
WHERE (productloc = productloc OR productloc IS NULL)
Hope it helps,
Sérgio

Using decode in where clause

I have a DECODE in my WHERE clause like this:
Where id = decode('&flag','Yes',(Select id from tab where id > 10),0)
This code works if the subquery returns one post. If I returns several I get an error like, ORA-01427, "Single-row subquery returns more than one row"
I've tried to change the '=' to an 'in' but I still get the same error!
Any ideas?
extended example:
WHERE Dop_id = (DECODE ('&prep_flag', 'Yes',
(SELECT Dop_id FROM
( SELECT DOP_id, name FROM TABLE)
WHERE name IS NOT NULL)
, Dop_id))
as mention this works if the select statmen returns on row, and not several.
Assuming decode is only expecting a single value where you have Select id from tab where id > 10 I would try moving the select outside of decode:
WHERE id IN (
SELECT decode('&flag', 'Yes', id, 0)
FROM tab
WHERE id > 10
)
WHERE Dop_id IN
( CASE &flag
WHEN 'Yes'
THEN (SELECT Dop_id
FROM TABLE
WHERE name IS NOT NULL)
ELSE Dop_id);

return a default record from a sql query

I have a sql query that I run against a sql server database eg.
SELECT * FROM MyTable WHERE Id = 2
This may return a number of records or may return none. If it returns none, I would like to alter my sql query to return a default record, is this possible and if so, how? If records are returned, the default record should not be returned. I cannot update the data so will need to alter the sql query for this.
Another way (you would get an empty initial rowset returned);
SELECT * FROM MyTable WHERE Id = 2
IF (##ROWCOUNT = 0)
SELECT ...
SELECT TOP 1 * FROM (
SELECT ID,1 as Flag FROM MyTable WHERE Id = 2
UNION ALL
SELECT 1,2
) qry
ORDER BY qry.Flag ASC
You can have a look to this post. It is similar to what you are asking
Return a value if no rows are found SQL
I hope that it can guide you to the correct path.
if not exists (SELECT top 1 * FROM mytable WHERE id = 2)
select * from mytable where id= 'whatever_the_default_id_is'
else
select * from mytable where id = 2
If you have to return whole rows of data (and not just a single column) and you have to create a single SQL query then do this:
Left join actual table to defaults single-row table
select
coalesce(a.col1, d.col1) as col1,
coalesce(a.col2, d.col2) as col2,
...
from (
-- your defaults record
select
default1 as col1,
default2 as col2,
...) as d
left join actual as a
on ((1 = 1) /* or any actual table "where" conditions */)
The query need to return the same number of fields, so you shouldn't do a SELECT * FROM but a SELECT value FROM if you want to return a default value.
With that in mind
SELECT value FROM MyTable WHERE Id = 2
UNION
SELECT CASE (SELECT count(*) FROM MyTable WHERE Id = 2)
WHEN 0 THEN 'defaultvalue'
END