3

I need to implement a conditional SELECT statement based on the result of another statement. I don't want to create a function for this purpose, but simply using conditional SELECT.

My unsuccessful approach looks as below:

DO
$do$
BEGIN
IF SELECT count(*) FROM table1 < 1 THEN
   SELECT * FROM table2;
   RETURN QUERY;

ELSE 
   SELECT * FROM table3;
   RETURN QUERY;
END IF;
END
$do$

I could accomplish the same result by checking the results of my query in PHP and based on this, perform another query, yet I'm wondering if it's possible to do this solely in PostgreSQL.

4
  • @NickBarnes I edited the post: first query has to count results and based on that another query has to return results. All queries in my particular case are quite long, so I decided to replace them with simpler equivalent. If you ask about columns, all 3 queries will have the same columns Commented Jun 15, 2015 at 10:59
  • return query is a single statement. It should be return query select ... - but a PL/pgSQL block can't return anything so you can't use return query in there anyway Commented Jun 15, 2015 at 10:59
  • @a_horse_with_no_name good point, is there any possible way to make PL/pgSQL return a query? Commented Jun 15, 2015 at 11:01
  • 1
    You can make a PL/PgSQL function return something, but not an anonymous block. Commented Jun 15, 2015 at 11:10

2 Answers 2

2

Try this:

with c as (select count(*) cnt from table1)
select table2.* from table2, c where c.cnt < 1
union all
select table3.* from table3, c where c.cnt >= 1
Sign up to request clarification or add additional context in comments.

4 Comments

In a general case if you want to know if a query does not exists is better NOT EXISTS than COUNT (*) < 1
Yes. If the condition is only about existence (like in the question) then EXISTS is certainly preferable.
@acesargl using with is preferred when you want to use a SELECT multiple times, you can also use with in your answer ;).
Using count you force to count all the tuples, using NOT EXISTS when one tuple is found the inner SELECT is aborted (EXISTS and NOT EXISTS usually use short-circuit or McCarthy evaluation.
2

If table2 and table3 are union-compatible then you can use a single SELECT:

SELECT * FROM table2 WHERE NOT EXISTS(SELECT * FROM table1)
UNION
SELECT * FROM table3 WHERE EXISTS(SELECT * FROM table1);

3 Comments

As a performance issue use UNION ALL instead of UNION ;).
I also suggest you to use SELECT 1 FROM table1 instead of SELECT * FROM table1 ;).
Exists and not exists ignore the projection list in the nested select. So, in this case, select * and select 1 are equivalent.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.