使用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中与记录相关的特定列的总和。这可能吗?
答案 0 :(得分:72)
有没有办法将该子选项存储为表中的伪列?
建议使用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,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);
创建模拟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
中的列,最后一个查询将动态返回所有当前列,其中视图只返回创建时存在的列(早期绑定与后期约束*
)
当然,您必须先删除依赖函数,然后才能删除表。在对表格进行更改时,您必须注意不要使函数无效。
答案 1 :(得分:2)
显然,根据Lion的评论,这是用视图处理的。所以在我的情况下,我使用了命令:
CREATE VIEW <viewname> AS
SELECT *, (SELECT sum(<col x>)
FROM <otherTable
WHERE <otherTable foreignkeyCol>=<thisTable keycol>) AS <col 3>
FROM <tablename>
它基本上给了我另一个表,包括所需的列。
答案 2 :(得分:2)
除了视图,您可以为总和创建一个函数。
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()的返回类型取决于您要汇总的列的类型。
答案 3 :(得分:2)
到目前为止,有三个答案,所有这些答案都有效。根据具体情况,其中任何一个都可能是“最佳解决方案”。对于小型表,性能应该非常接近,但它们都不可能很好地扩展到具有数百万行的表。使用大型数据集获得所需结果的最快方法可能是(使用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
是 a_id
上的功能相关。
SELECT a_id, col1, col2, sum(colx)
FROM tbl_a LEFT JOIN tbl_b b using(a_id)
GROUP BY a_id;
视图可以通过这种方式定义并且可以扩展,但我不会认为所有相同的执行路径将被考虑用于使用函数的方法,因此最快的执行路径可能不会使用。