Postgresql 合并视图/在现有视图上添加条件

Postgresql 合并视图/在现有视图上添加条件,postgresql,view,filter,criteria,Postgresql,View,Filter,Criteria,我有一个存储在schemaschem1中的顶级视图,它从一些表中驱动数据,屏蔽不相关的数据。 应用程序对数据发出多个不同的标准,以便出于其他原因屏蔽其他行 数据处理是通过存储过程完成的。我希望应用程序能够将它想要(或不想要)的任何过滤器发回临时视图,这样应用程序就可以按照自己的意愿“添加”过滤器,换句话说,我正在寻找一种存储临时视图的方法,该方法可以驱动新视图取代它的前一个临时视图中的数据 我想要实现的另一种解释是,在现有视图的基础上组合新标准,以便对该视图的休闲引用将使用“基本视图+新标准”

我有一个存储在schema
schem1
中的顶级
视图
,它从一些表中驱动数据,屏蔽不相关的数据。 应用程序对数据发出多个不同的标准,以便出于其他原因屏蔽其他行

数据处理是通过存储过程完成的。我希望应用程序能够将它想要(或不想要)的任何过滤器发回临时视图,这样应用程序就可以按照自己的意愿“添加”过滤器,换句话说,我正在寻找一种存储临时视图的方法,该方法可以驱动新视图取代它的前一个临时视图中的数据

我想要实现的另一种解释是,在现有视图的基础上组合新标准,以便对该视图的休闲引用将使用“基本视图+新标准”

据我所知,pgsql并不“编译”视图,而是将其作为SQL文本使用,因此引用相同的
视图被视为递归调用(实际上我想做的是引用FROM子句中的“上一层视图”。

一个选项(如果您有其他想法,请回答)是从视图的模式定义中提取查询,并将其指定为新过滤器要从中提取的表

i、 e.如果视图是

select * from users;
然后,我们删除旧视图,并使用现有视图创建具有新条件的新视图 新视图将由如下查询组成

select * FROM ( select * from users ) as t where user_id>100

通过这种方式,可以以类似的方式在每个过滤器上添加其他过滤器。

听起来您实际上在寻找一个临时表,例如:

create temporary table current_data as
select * from filtered_view;

如果额外的行不在其中,则根据需要进行直接插入,如果不在其中,则进行反连接,例如:

insert into current_data
select * from other_view
left join current_data using (whatever_pkey)
where current_data is null;

填充完临时表后,运行
分析当前的\u数据
,如果其中包含足够的数据,则创建适用的索引,然后继续在查询中使用它,就像通常一样。

postgres中的视图不是动态筛选数据的最佳工具。 每次定义新过滤器时创建新视图都会带来麻烦(更不用说性能成本了)

为了在应用程序中生成报告,我使用返回查询的函数。 这些函数将筛选器值作为参数。 可以将它们视为参数化视图。

为了满足您的条件,我提出以下解决方案。 当然,这只是一个提纲

假设customers是您的顶级视图,它包含字段name

创建一个表,我们将在其中存储编号过滤器:

create table filters (
    id serial primary key,
    filter text);
要定义新过滤器,只需将其插入表中:

insert into filters (filter)
values ('name like ''%John%''');
并将我们的参数化视图定义为一个函数,该函数从客户中生成数据,并通过表过滤器中的值进行过滤:

create or replace function show_customers()
    returns setof customers
    language plpgsql
as $$
declare
    _filter text;
    _query text = 'select * from customers where true ';
begin
    for _filter in 
        select filter from filters order by id
    loop
        _query = _query || ' and (' || _filter || ')';
    end loop;
    return query execute _query;
end $$;
现在,如果调用该函数,您将根据过滤器的当前状态获得过滤数据

select * from show_customers();

请注意,您可以完全控制当前过滤器。您可以通过清空表筛选器来重置它们,您可以删除一个或多个,依此类推。

否,临时表将填充数据,将导致不必要的内存开销,可能会填充不相关的数据,我相信这将导致性能降级。特别查询在这里是最好的,因为条件字段会根据需要被索引。呃,除非你这样填充,否则它不会有不相关的数据。无论如何,正如您已经发现的,您不能使用视图的定义来更改视图。所以我指出了(imho)可靠的替代方案。当然,但如果我需要在应用程序知道过滤器后填充它,那又有什么用呢。这个选择很明显,对不起。对我来说最好的事情可能是,如果我能用另一个临时视图覆盖临时视图——只要想到另一个想法——一个词,性能。在这个问题上,您的意图不是很清楚,但是如果您的这个视图是为了创建复杂的报告,那么您最好使用一个或多个临时表,而不是使用大量(更不用说可变)视图。从另一方面来说,如果你每天都在研究这个问题,那么——无意冒犯——你的方法可能是不正确的。如果是后者,请根据需要定义一个视图或十个视图,并在其上适当地应用where子句,或者使用ORM和查询生成器为您生成这些where子句。顺便说一句,不要尝试在查询中执行太多操作。通常最好检索最后一组行,然后使用(…)
子句中的
从依赖项中获取相关行,而不是尝试使用带有复杂where group by子句的巨型联接一次性获取所有内容。关于ORM,其中一些现在已经相当不错了,例如Ruby中的Sequel拥有成熟的查询构建器,当与Postgres一起使用时,这些构建器非常合适。PHP中的原则也很好。只需远离“传统”的ActiveRecord模式:使用带有适当AST(抽象语法树)的ORM。是的,除非您有任何类型的聚合,否则这是有效的。如果您的示例视图更像是按id从用户组中选择id、sum(字段),则您可能会遇到naster性能问题。我的解决方案甚至可能不起作用,SP已编译,我们可能无法删除视图,因为SP是依赖的。Ya:如果您删除视图,SP也将被删除。顺便说一句,SP不是“编译”的,而是在第一次调用时准备并缓存它们的查询计划。(这比现实中的要聪明一点,但这就是事情的要点。)首先,这是一个很酷的想法,其次,
参数化视图
?如果需要跨整个表执行,即使限制为1(SP),请不要将其作为视图引用。(视图的性能成本是多少?视图的操作就像我将标准添加到SP中的引用表中一样。SP应