将常用查询存储为列?
使用PostgreSQL,我有一些看起来像这样的查询:
SELECT <col 1>, <col 2> , (SELECT sum(<col x>) FROM <otherTable> WHERE <other table foreignkeyCol>=<this table keycol>) AS <col 3> FROM <tbl>
假设子select在每种情况下都是相同的,那么有没有办法将这个子select存储为表中的伪列? 从本质上讲,我希望能够从表A中select一个列,这是表B中与logging相关的特定列的总和。 这可能吗?
有没有办法将该子select存储为表中的伪列?
像一个VIEW
已被build议是一个完全有效的解决scheme。 但是还有另外一种方式更适合你的问题。 您可以编写一个函数,将表types作为参数来模拟 “计算字段”或“生成列” 。
考虑这个testing用例,从你的描述中得出:
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);
创build模拟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
。 这是必不可less的 。
与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 ;
更多关于在手册。
你现在可能已经看到,这是怎么回事。 这看起来像添加表tbl_a
的额外列,而col3()
实际上是一个函数,它将tbl_a
(或其别名)的当前行作为行types参数并计算一个值。
SELECT *, a.col3 FROM tbl_a AS a;
如果有一个实际的列col3
它会占用优先权,并且系统不会以行tbl_a
作为参数来查找该名称的函数。
它的美妙之处在于:你可以添加或删除tbl_a
列,最后一个查询将dynamic返回所有当前列,其中一个视图只会返回在创build时存在的列(早期绑定与*
后期绑定)。
当然,你必须先删除依赖函数,然后才能放下表格。 在更改表格时,必须注意不要使函数无效。
到目前为止有三个答案,所有这些工作。 根据具体情况,其中任何一项都可能是“最佳解决scheme”。 对于小型表格,性能应该非常接近,但是没有一个可以很好地扩展到有数百万行的表格。 使用大型数据集获得所需结果的最快方法可能是(使用Erwin的设置):
SELECT a_id, col1, col2, sum(colx) FROM tbl_a LEFT JOIN tbl_b b using(a_id) GROUP BY a_id, col1, col2;
如果将a_id
声明为主键,并且在9.1或更高版本下运行,则可以简化GROUP BY
子句,因为col1
和col2
在function上依赖于a_id
。
SELECT a_id, col1, col2, sum(colx) FROM tbl_a LEFT JOIN tbl_b b using(a_id) GROUP BY a_id;
视图可以用这种方式来定义,并且可以扩展,但是我不认为使用函数的方法将考虑所有相同的执行path,所以最快的执行path可能不被使用。
除了一个视图,你可以创build一个函数的总和。
CREATE FUNCTION sum_other_table( key type_of_key ) RETURNS bigint AS $$ SELECT sum( col_x ) FROM table_1 where table_1.key = key $$ LANGUAGE SQL;
然后用它作为你的聚合器:
SELECT col_1, col_2, sum_other_table( key ) AS col_3 FROM table_2 WHERE table_2.key = key;
请注意,sum_other_table()的返回types取决于您正在总结的列的types。
显然这是根据狮子的意见处理的。 所以在我的情况下,我使用了这个命令:
CREATE VIEW <viewname> AS SELECT *, (SELECT sum(<col x>) FROM <otherTable WHERE <otherTable foreignkeyCol>=<thisTable keycol>) AS <col 3> FROM <tablename>
这基本上给了我另一张桌子,包括所需的列。