PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Memorizzare la query comune come colonna?

C'è un modo per memorizzare quella sottoselezione come pseudo-colonna nella tabella?

Un VIEW come è stato consigliato è una soluzione perfettamente valida. Provaci.

Ma c'è un altro modo che si adatta ancora di più alla tua domanda. Puoi scrivere una funzione che accetta il tipo di tabella come parametro da emulazione un "campo calcolato" o "colonna generata" .

Considera questo test case, derivato dalla tua descrizione:

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);

Crea una funzione che 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$;

Ora puoi interrogare:

SELECT a_id, col1, col2, tbl_a.col3
FROM   tbl_a;

O anche:

SELECT *, a.col3 FROM tbl_a a;

Nota come ho scritto tbl_a.col3 / a.col3 , non solo col3 . Questo è essenziale .

A differenza di una "colonna virtuale" in Oracle, non incluso automaticamente in un SELECT * FROM tbl_a . Potresti usare un VIEW per quello.

Perché funziona?

Il modo comune per fare riferimento a una colonna di una tabella è con notazione attributo :

SELECT tbl_a.col1 FROM tbl_a;

Il modo comune per chiamare una funzione è con notazione funzionale :

SELECT col3(tbl_a);

In generale, è meglio attenersi a questi metodi canonici , che sono d'accordo con lo standard SQL.

Ma Postgres consente anche la notazione degli attributi. Funzionano anche questi:

SELECT col1(tbl_a) FROM tbl_a;
SELECT tbl_a.col3;

Maggiori informazioni su questo nel manuale.
Probabilmente ormai hai visto dove sta andando. Questo sembra come se aggiungessi una colonna extra della tabella tbl_a mentre col3() è in realtà una funzione che prende la riga corrente di tbl_a (o il suo alias) come argomento di tipo riga e calcola un valore.

SELECT *, a.col3
FROM   tbl_a AS a;

Se esiste una colonna effettiva col3 ha la priorità e il sistema non cerca una funzione con quel nome prendendo la riga tbl_a come parametro.

Il "bello":puoi aggiungere o eliminare colonne da tbl_a e l'ultima query restituirà dinamicamente tutte le colonne correnti, dove una vista restituirebbe solo le colonne che esistevano al momento della creazione (associazione anticipata vs. associazione tardiva di * ).
Ovviamente, devi eliminare la funzione dipendente prima di poter eliminare la tabella ora. E devi fare attenzione a non invalidare la funzione quando apporti modifiche alla tabella.

Non lo userei ancora. È troppo sorprendente per il lettore innocente.