Existe uma maneira de armazenar essa sub-seleção como uma pseudo-coluna na tabela?
Uma
VIEW
como foi aconselhado é uma solução perfeitamente válida. Vá em frente. Mas há outra maneira que se encaixa ainda mais na sua pergunta. Você pode escrever uma função que use o tipo de tabela como parâmetro para emular um "campo calculado" ou "coluna gerada" .
Considere este caso de teste, derivado de sua descrição:
CREATE TABLE tbl_a (a_id int, col1 int, col2 int);
INSERT INTO tbl_a VALUES (1,1,1), (2,2,2), (3,3,3), (4,4,4);
CREATE TABLE tbl_b (b_id int, a_id int, colx int);
INSERT INTO tbl_b VALUES
(1,1,5), (2,1,5), (3,1,1)
, (4,2,8), (5,2,8), (6,2,6)
, (7,3,11), (8,3,11), (9,3,11);
Criar função que emula
col3
:CREATE FUNCTION col3(tbl_a)
RETURNS int8
LANGUAGE sql STABLE AS
$func$
SELECT sum(colx)
FROM tbl_b b
WHERE b.a_id = $1.a_id
$func$;
Agora você pode consultar:
SELECT a_id, col1, col2, tbl_a.col3
FROM tbl_a;
Ou ainda:
SELECT *, a.col3 FROM tbl_a a;
Observe como escrevi
tbl_a.col3
/ a.col3
, não apenas col3
. Isso é essencial . Ao contrário de uma "coluna virtual" no Oracle, não incluído automaticamente em um
SELECT * FROM tbl_a
. Você pode usar um VIEW
por isso. Por que isso funciona?
A maneira comum de fazer referência a uma coluna de tabela é com notação de atributo :
SELECT tbl_a.col1 FROM tbl_a;
A maneira comum de chamar uma função é com notação funcional :
SELECT col3(tbl_a);
Geralmente, é melhor manter essas formas canônicas , que concordam com o padrão SQL.
Mas o Postgres também permite a notação de atributos. Estes também funcionam:
SELECT col1(tbl_a) FROM tbl_a; SELECT tbl_a.col3;
Mais sobre isso no manual.
Você provavelmente já viu onde isso está indo. Este parece como se você adicionasse uma coluna extra da tabela
tbl_a
enquanto col3()
é na verdade uma função que pega a linha atual de tbl_a
(ou seu alias) como argumento de tipo de linha e calcula um valor. SELECT *, a.col3
FROM tbl_a AS a;
Se houver uma coluna real
col3
tem prioridade e o sistema não procura uma função com esse nome pegando a linha tbl_a
como parâmetro. A "beleza" disso:você pode adicionar ou remover colunas de
tbl_a
e a última consulta retornará dinamicamente todas as colunas atuais, onde uma exibição retornaria apenas as colunas que existiam no momento da criação (ligação inicial vs. ligação tardia de *
).Claro, você tem que descartar a função dependente antes de poder descartar a tabela agora. E você deve tomar cuidado para não invalidar a função ao fazer alterações na tabela.
Eu ainda não usaria. É muito surpreendente para o leitor inocente.