使用Postgresql,我有一些看起来像这样的查询:
SELECT <col 1>,<col 2>,(SELECT sum(<col x>) FROM <otherTable> WHERE <other table foreignkeyCol>=<this table keycol>) AS <col 3> FROM <tbl>
假定子选择在每种情况下都是相同的,有没有办法将该子选择作为伪列存储在表中?基本上,我想能够从表A中选择一个列,该列是来自表B中记录相关的特定列的总和。这可能吗?
Is there a way to store that sub-select as a pseudo-column in the table?
一个VIEW
喜欢被建议是一个完全有效的解决方案。但还有另一种方式更适合你的问题。您可以编写一个函数,将表类型作为参数来模拟“计算字段”或“生成列”。
考虑这个测试用例,源自您的描述:
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,5),8),(5,(6,6),(7,11),(8,(9,11);
创建模仿col3的函数:
CREATE FUNCTION col3(tbl_a) RETURNS int8 AS $func$ SELECT sum(colx) FROM tbl_b b WHERE b.a_id = $1.a_id $func$ LANGUAGE sql STABLE;
现在可以查询:
SELECT a_id,col1,col2,tbl_a.col3 FROM tbl_a;
甚至:
SELECT *,a.col3 FROM tbl_a a;
注意我如何写tbl_a.col3 / a.col3,而不只是col3。这是必要的。
与“virtual column” in Oracle不同,它不会自动包含在SELECT * FROM tbl_a中。你可以使用VIEW。
为什么这个工作?
SELECT tbl_a.col1 FROM tbl_a;
SELECT col3(tbl_a);
一般来说,最好坚持这些规范的方式,这符合sql标准。
但在Postgresql中,函数符号和属性符号是等价的。所以这些工作以及:
SELECT col1(tbl_a) FROM tbl_a; SELECT tbl_a.col3;
More about that in the manual.
你现在可能看到,这是怎么回事。这看起来像你会添加表tbl_a的额外的列,而col3()实际上是一个函数,它将tbl_a(或其别名)的当前行作为行类型参数,并计算一个值。
SELECT *,a.col3 FROM tbl_a AS a;
如果有一个实际的列col3,它优先,系统不会查找该行的函数tbl_a作为参数。
它的美妙之处在于:您可以从tbl_a添加或删除列,最后一个查询将动态返回所有当前列,其中视图只返回创建时存在的列(早期绑定与*的早期绑定)。当然,你必须删除自定义函数,然后才能删除表。并且,在更改表时,必须注意不要使函数无效。