sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Almacenar consulta común como columna?

¿Hay alguna forma de almacenar esa subselección como una pseudocolumna en la tabla?

Una VIEW como se ha aconsejado es una solución perfectamente válida. Anímate.

Pero hay otra forma que se ajusta aún más a su pregunta. Puede escribir una función que tome el tipo de tabla como parámetro para emular un "campo calculado" o "columna generada" .

Considere este caso de prueba, derivado de su descripción:

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

Crear función que emule 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$;

Ahora puedes consultar:

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

O incluso:

SELECT *, a.col3 FROM tbl_a a;

Tenga en cuenta cómo escribí tbl_a.col3 / a.col3 , no solo col3 . Esto es esencial .

A diferencia de una "columna virtual" en Oracle, no incluido automáticamente en un SELECT * FROM tbl_a . Podrías usar un VIEW por eso.

¿Por qué funciona esto?

La forma común de hacer referencia a una columna de tabla es con notación de atributo :

SELECT tbl_a.col1 FROM tbl_a;

La forma común de llamar a una función es con notación funcional :

SELECT col3(tbl_a);

En general, es mejor adherirse a estas formas canónicas , que están de acuerdo con el estándar SQL.

Pero Postgres también permite la notación de atributos. Estos también funcionan:

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

Más sobre eso en el manual.
Probablemente ya sepa adónde va esto. Esto parece como si agregara una columna adicional de la tabla tbl_a mientras col3() es en realidad una función que toma la fila actual de tbl_a (o su alias) como argumento de tipo de fila y calcula un valor.

SELECT *, a.col3
FROM   tbl_a AS a;

Si hay una columna real col3 tiene prioridad y el sistema no busca una función de ese nombre tomando la fila tbl_a como parámetro.

La "belleza" de esto:puede agregar o quitar columnas desde tbl_a y la última consulta devolverá dinámicamente todas las columnas actuales, donde una vista solo devolvería las columnas que existían en el momento de la creación (enlace anticipado frente a enlace tardío de * ).
Por supuesto, debe descartar la función dependiente antes de poder descartar la tabla ahora. Y debe tener cuidado de no invalidar la función al realizar cambios en la tabla.

Todavía no lo usaría. Es demasiado sorprendente para el lector inocente.