Условный джойн по наличию записей

Есть две таблицы A (id1, id2) и B (id, a_id1, a_id2, ...). В A порядка 10-20 записей. В B десятки тысяч. Индексы A(id1, id2) и B(a_id1, a_id2) в наличии.

Нужно в одном запросе объединить два таких запроса

IF (EXISTS (SELECT 1 FROM a)) THEN
  SELECT
    b.*
  FROM
    b
    JOIN a ON (
      a.id1 = b.a_id1 AND
      a.id2 = b.a_id2
    );
ELSE
  SELECT
    b.*
  FROM
    b;

Можно что-то придумать?

Все происходит в процедуре, поэтому можно предварительно выполнить какие-то действия.

Писать два запроса не хочу, т.к. у запроса может быть еще куча параметров по таблице B


Update

Наваял так. На сколько дико?

SELECT
  b.*
FROM
  b
WHERE
  NOT EXISTS (SELECT 1 FROM a) OR
  EXISTS (
    SELECT
      1
    FROM a 
    WHERE
      a.id1 = b.a_id1 AND a.id2 = b.a_id2
  )

Ответы (1 шт):

Автор решения: Герман Борисов

На сколько дико?

Второй вариант вполне нормальный, если в таблице a не бывает большого количества записей или добавлены индексы, удобные для выборки.

Upadte

Дополню, раз уж местное сообщество недовольно столь коротким ответом.

Изначально interbase (наследником которого является firebird) не был рассчитан на сложные запросы. Всю логику предполагалось реализовывать в хранимых процедурах на IF'ах и циклах. С этой точки зрения для производительности лучше оставить ветвление с двумя разными запросами.

Если SELECT b.* FROM b идет в цикле с неявным курсом FOR ... DO ..., то есть еще один вариант:

  1. Перед циклом делаете проверку IF (EXISTS (SELECT * FROM a)) и результат сохраняете в переменную-флаг.
  2. В цикле проверяете флаг, и если он не установлен, то выполняете проверку IF (EXISTS (SELECT * FROM a WHERE a.id1 = :a_id1 AND a.id2 = :a_id2)) в зависимости от результата которой или продолжаете обработку или переходите к следующей итерации (CONTINUE );
→ Ссылка