Условный джойн по наличию записей
Есть две таблицы 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 ..., то есть еще один вариант:
- Перед циклом делаете проверку
IF (EXISTS (SELECT * FROM a))и результат сохраняете в переменную-флаг. - В цикле проверяете флаг, и если он не установлен, то выполняете проверку
IF (EXISTS (SELECT * FROM a WHERE a.id1 = :a_id1 AND a.id2 = :a_id2))в зависимости от результата которой или продолжаете обработку или переходите к следующей итерации (CONTINUE);