Two SQL statements, ignore the return of the first if it has no results? - sql

I have a sql statement SELECT * FROM table1 WHERE ....; SELECT * FROM table2 WHERE ....
What I want is to get the results from the first select statement if it returns results, but if it doesn't, I want to ignore it and just get the results from the second select statement. Is there a way I can do this just using SQL?
I'm getting this returned to me as a datatable, using a dataadapter to fill the datatable from the above SQL statement. I can't change that part, or switch to filling a dataset (for reasons I won't get into, but it just can't be changed).

Assuming both queries return the same number and type of columns, one way to do this would be:
select * from table1 where ... /* query 1 conditions */
union all
select * from table2 where ... /* query 2 conditions */
and not exists
(select 1 from table1 where ... /* query 1 conditions */)

A couple options. You can check the count first:
If (select count(*) from table1 where...) > 0
begin
select * from table1 where...
end
else
begin
select * from table2 where...
end;
if both result sets are identical in structure, you can save the count check (and thus improve performance) by using a temp table:
create table #temp (col1 int, col2 varchar(10), ...);
insert #temp
select * from table1 where...;
if ##rowcount = 0
begin
insert #temp
select * from table2 where...
end;
select * from #temp;

Related

How to UNION a list of tables retrieved from another table with a single query?

I have a table with a list of tables in PostgreSQL:
|id|table |
|--|------|
|1 |table1|
|2 |table2|
|3 |table3|
I want to select from a union of all these tables like (pseudo-code):
select * from union(select table from tablenames)
To automate this, you need dynamic SQL
CREATE OR REPLACE FUNCTION f_multi_select()
RETURNS SETOF table1
LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE
(
SELECT string_agg(format('SELECT * FROM %I', tbl), ' UNION ALL ')
FROM (SELECT tbl FROM tablenames ORDER BY id) sub
);
END
$func$;
Call:
SELECT * FROM f_multi_select();
Assuming that all tables share the same row type - so we can pick any to define the return type of the function.
I threw in a subquery with ORDER BY - in case the order of tables is meaningful.
Related:
Return SETOF rows from PostgreSQL function
Table name as a PostgreSQL function parameter
Here is one way you can do this without using dynamic SQL. Let's say that you only had 10 possible tables in your schema. Then, you could write the following query:
select * from table1 where 'table1' in (select "table" from tablenames) union all
select * from table2 where 'table2' in (select "table" from tablenames) union all
select * from table3 where 'table3' in (select "table" from tablenames) union all
...
select * from table10 where 'table10' in (select "table" from tablenames);
The drawback of this approach is that it requires hard coding a query for each possible table.
I also assume here that select * makes sense, because each of the ten tables would have the same number and types of columns.

SQL server: IF EXISTS insert x into table A, else insert y into table A

I am getting error of "#DateRange already in the database". What I want is, if there is data in #daterange2, then do the union, else only select from #DateRange1. But the destination table would both be in #DateRange table.
Here is my code:
IF exists (SELECT * FROM #DateRange2)
SELECT * INTO #DateRange
FROM
(SELECT * FROM
#DateRange1
UNION
SELECT * FROM
#DateRange2
) a
ELSE
SELECT * INTO #DateRange
FROM
#DateRange1
Uh, why bother with the conditional logic at all? Just do:
SELECT *
INTO #DateRange
FROM (SELECT *
FROM #DateRange1
UNION
SELECT *
FROM #DateRange2
) a;
If there are no rows in the second table, then none get inserted.
Also, check whether you really need UNION. In general, UNION ALL is preferred -- unless you really want to incur the overhead of removing duplicates.

Select All Values From Table That Match All Values of Subquery

So I have a list of values that is returned from a subquery and would like to select all values from another table that match the values of that subquery. Is there a particular way that's best to go about this?
So far I've tried:
select * from table where tableid = select * from table1 where tableid like '%this%'
select * from table where tableid in(select tableid
from table1
where tableid like '%this%')
select * from table where tableid IN
(select tableid from table1 where tableid like '%this%')
A sub-query needs to return what you are asking for. Additionally, if there's more than 1 result, you need IN rather than =
This will work
select * from table where tableid in
(select tableid from table1 where tableid like '%this%')
= works when subquery returns 1 record only
in works when subquery returns 1 or more than one record only
I am reading a SQL Server book right now, and it highlights doing this using the EXISTS statement in the WHERE clause for speed and efficiency purposes. Here's a potential solution.
SELECT
*
FROM
tableName AS t
WHERE
EXISTS(
SELECT
1
FROM
table1 AS s --as in subtable or something like that
WHERE
t.tableid = s.tableid
AND
s.tableid like '%this%'
)

Reuse select query in a procedure in Oracle

How would I store the result of a select statement so I can reuse the results with an in clause for other queries? Here's some pseudo code:
declare
ids <type?>;
begin
ids := select id from table_with_ids;
select * from table1 where id in (ids);
select * from table2 where id in (ids);
end;
... or will the optimizer do this for me if I simply put the sub-query in both select statements?
EDIT: Here's more information about the structure of my tables.
Basically table1 is a standard table with the id being the primary key. While table2 has a 3-column primary key with id being one of those columns. In my case the id in table2 will appear in three rows.
You could use a SQL table object to store the result of the select and reuse it. It will consume more memory and will probably be efficient only if the first SELECT takes a lot of time.
CREATE TYPE tab_number IS TABLE OF NUMBER;
/
You would use it with a BULK COLLECT INTO clause:
DECLARE
ids tab_number;
BEGIN
SELECT id BULK COLLECT INTO ids FROM table_with_ids;
SELECT * /*into ??*/
FROM table1
WHERE id IN (SELECT column_value FROM TABLE(ids));
SELECT * /*into ??*/
FROM table2
WHERE id IN (SELECT column_value FROM TABLE(ids));
END;
In version 9i and before you would need to use CAST to query the table:
SELECT *
FROM table2
WHERE id IN (SELECT column_value FROM CAST (TABLE(ids) AS tab_number));
Alternatively, you could use a GLOBAL TEMPORARY TABLE to store the intermediate result set.

Unselect the previous select

I don't know it may sound weird... but here is my situation... I have to select rows from two tables (Table1) and (Table2)
Select * from Table1 Where <SomeCondition>
Select * from Table2 Where <SomeCondition>
But my constraint is If Table1 / Table2 return 0(zero) Rows... I should not return any results at all.
That ie... If 1st select returns say 10 rows and the 2nd select returns 0 (zero) rows, I should call back the first select also...
Is the Temp tables the only solution, or do we have any other alternative.
Thanks in advance for your response...
Raja
One approach is to do an IF EXISTS first:
IF EXISTS(SELECT * FROM Table1 WHERE....) AND EXISTS(SELECT * FROM Table2 WHERE....)
BEGIN
-- Now do your SELECT on each, as both return results
END
EXISTS should give good performance, as it will stop as soon as it does find a matching record.
Without more details of your specific queries, here is an option. As long as your queries aren't too complex aren't very intensive, this should work:
Select * from Table1 Where <SomeCondition>
where exists( Select null from Table2 Where <SomeCondition> );
Select null from Table2 Where <SomeCondition>
where exists ( Select null from Table1 Where <SomeCondition> );
This will only select rows in each statement if the other statement will also return any number of rows greater than zero.
An obvious but not-so-performant solution will be to count number of rows first (not sure about the syntax):
if not exists(select id from Table1 where ...) or not exists(select id from Table1 where ...)
return
Select * from Table1 Where <SomeCondition>
Select * from Table2 Where <SomeCondition>
If you can use stored procedures you can use ##rowcount to check if the second query returned any results:
create proc pTest
as
Select * from Table1 Where <SomeCondition>
Select * from Table2 Where <SomeCondition>
if ##rowcount = 0 return
go