Eu tenho duas mesas:
parent
com colunasidentifier
(pkey) eperiod
;child
com colunasidentifier
(pkey)parent_identifier
eperiod
.
Existem colunas adicionais, mas não as listei aqui porque não são realmente relevantes.
Eu quero selecionar os períodos da seguinte forma:
- Se o
parent
corresponder a algum predicado, escolhaparent.period
. - Se não, então escolha
child.period
de cada criança.
Tenho a seguinte consulta:
select q.period
from parent,
lateral (
select parent.period
where <some complex predicate>
union all
select child.period
from child
where child.parent_identifier = parent.identifier and
not(<the same complex predicate as above>)
) as q(period);
Enquanto esta consulta funciona e retorna os períodos esperados, gostaria de saber se esta consulta poderia ser reescrita de tal forma que <some complex predicate>
não precise ser avaliada duas vezes, para melhorar o desempenho (embora por um pequeno fator) e a estrutura geral da consulta para representar o if ... else ...
de cima . Idealmente, eu quero fazer um loop em cada linha parent
/ child
e avaliar o predicado apenas uma vez.
Tentei introduzir uma case when <some complex predicate> then ... else ... end
cláusula, mas não consegui acertar. Não tenho certeza se isso é possível na FROM
cláusula. Isso é possível?
Eu também tinha select case when <predicate> then parent.period else unnest(array(select child.period from child where ...)) from parent
em mente (embora eu não tenha tentado, então pode ser proibido em um case when ...
também), mas não tenho certeza se primeiro criar e depois desaninhar uma matriz é realmente ideal. Além disso, não gosto muito de funções de retorno de conjunto, como unnest
, na seleção.
As consultas a seguir avaliam o predicado caro apenas uma vez para cada
parent
linha. Para conseguir isso, o predicado é avaliado em uma subconsulta separada. A primeira versão usa uma junção lateral, a segunda uma junção interna. Isso atende aos requisitos da pergunta.