PostgreSQL中的计算/计算/虚拟/派生列

时间:2011-11-23 23:16:48

标签: postgresql calculated-columns materialized-views sql-view

PostgreSQL是否支持计算/计算列,如MS SQL Server?我在文档中找不到任何内容,但由于此功能包含在许多其他DBMS中,我认为我可能会遗漏一些内容。

例如:http://msdn.microsoft.com/en-us/library/ms191250.aspx

7 个答案:

答案 0 :(得分:89)

不支持Postgres 11 生成的列 - 如SQL标准中所定义,并由包括DB2,MySQL和Oracle在内的某些RDBMS实现。也不是SQL Server的类似“计算列”

该特征是in development for Postgres 12,主要作者Peter Eisentraut。

目前,您可以使用功能模拟属性符号tbl.col外观和工作原理很像虚拟生成列。由于历史原因,这在Postgres中存在一些语法怪异,恰好适合这种情况。此相关答案包含代码示例

表达式(看起来像一列)不包含在SELECT * FROM tbl中。您必须明确地列出它。

也可以使用匹配的表达式索引支持 - 只要函数为IMMUTABLE。像:

CREATE FUNCTION col(tbl) ... AS ...  -- your computed expression here
CREATE INDEX ON tbl(col(tbl));

替代

或者,您可以使用VIEW实现类似的功能,可选择与表达式索引结合使用。然后SELECT *可以包含生成的列。

“持久”计算列可以使用triggers以功能相同的方式实现。

Materialized views是一个密切相关的概念,implemented since Postgres 9.3 在早期版本中,可以手动管理MV。

答案 1 :(得分:23)

是的,你可以!! 解决方案应该简单,安全,高效......

我是postgresql的新手,但似乎你可以使用expression index创建计算列,并与view配对(视图是可选的,但会让生活变得更轻松)。

假设我的计算是md5(some_string_field),那么我将索引创建为:

CREATE INDEX some_string_field_md5_index ON some_table(MD5(some_string_field));

现在,任何作用于MD5(some_string_field)的查询都将使用索引,而不是从头开始计算。例如:

SELECT MAX(some_field) FROM some_table GROUP BY MD5(some_string_field);

您可以使用explain进行检查。

但是,此时您依赖于表的用户知道如何构建列。为了简化生活,您可以在原始表的增强版本上创建VIEW,将计算值添加为新列:

CREATE VIEW some_table_augmented AS 
   SELECT *, MD5(some_string_field) as some_string_field_md5 from some_table;

现在,使用some_table_augmented的任何查询都可以使用some_string_field_md5而无需担心它是如何工作的......它们只是获得了良好的性能。该视图不会复制原始表中的任何数据,因此它在内存方面和性能方面都很好。但请注意,您无法更新/插入视图,只能进入源表,但如果您真的需要,我相信您可以使用rules将插入和更新重定向到源表(我可能错了)最后一点,因为我自己从未尝试过。)

编辑:似乎查询涉及竞争索引,计划程序引擎有时可能根本不使用表达式索引。选择似乎取决于数据。

答案 2 :(得分:12)

执行此操作的一种方法是使用触发器!

CREATE TABLE computed(
    one SERIAL,
    two INT NOT NULL
);

CREATE OR REPLACE FUNCTION computed_two_trg()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
AS $BODY$
BEGIN
    NEW.two = NEW.one * 2;

    RETURN NEW;
END
$BODY$;

CREATE TRIGGER computed_500
BEFORE INSERT OR UPDATE
ON computed
FOR EACH ROW
EXECUTE PROCEDURE computed_two_trg();

在更新或插入行之前触发触发器。它会更改我们要计算NEW记录的字段,然后返回该记录。

答案 3 :(得分:0)

我有一个有效的代码并且使用了计算的术语,我不是在postgresSQL纯粹的,我们在PADB上运行

这是如何使用

create table some_table as
    select  category, 
            txn_type,
            indiv_id, 
            accum_trip_flag,
            max(first_true_origin) as true_origin,
            max(first_true_dest ) as true_destination,
            max(id) as id,
            count(id) as tkts_cnt,
            (case when calculated tkts_cnt=1 then 1 else 0 end) as one_way
    from some_rando_table
    group by 1,2,3,4    ;

答案 4 :(得分:0)

PostgreSQL 12支持生成的列:

  

PostgreSQL 12 Beta 1 Released!

     

生成的列

     

PostgreSQL 12允许创建生成的列,并使用其他列的内容使用表达式来计算其值。此功能提供了存储的生成的列,这些列是在插入和更新时计算的,并保存在磁盘上。虚拟的生成的列(仅当将列作为查询的一部分读取时才计算)尚未实现。 >


  

Generated Columns

     

生成的列是一个特殊列,总是从其他列计算得出。因此,表的视图就是列。

CREATE TABLE people (
    ...,
    height_cm numeric,
    height_in numeric GENERATED ALWAYS AS (height_cm * 2.54) STORED
);

答案 5 :(得分:-2)

好吧,不确定这是否是您的意思,但Posgres通常支持“虚拟” ETL语法。 我在表中创建了一个空列,然后需要根据行中的值通过计算的记录来填充它。

UPDATE table01
SET column03 = column01*column02; /*e.g. for multiplication of 2 values*/
  1. 这太蠢了,我怀疑这不是您想要的。
  2. 显然它不是动态的,您只需运行一次。但是没有任何障碍可以触发它。

答案 6 :(得分:-4)

具有Check约束的轻量级解决方案:

CREATE TABLE example (
    discriminator INTEGER DEFAULT 0 NOT NULL CHECK (discriminator = 0)
);