我已经找到了解决方案(我认为)我将要求在Oracle和SQL Server上提出的问题,但似乎无法将其转化为Postgres解决方案。我正在使用Postgres 9.3.6。
我们的想法是能够生成元数据"关于用于分析目的的表格内容。这只能通过为每列运行查询来完成(AFAIK),以便找出,例如...... min / max / count值等。为了使过程自动化,最好让DB生成查询,然后执行。
使用示例salesdata
表,我能够为每列生成选择查询,并使用以下代码段返回min()值:
SELECT 'SELECT min('||column_name||') as minval_'||column_name||' from salesdata '
FROM information_schema.columns
WHERE table_name = 'salesdata'
优点是db将生成代码而不管列数。
现在我想到了无数的地方存储这些查询,无论是某种变量还是表格列,我们的想法是让这些查询执行。
我想过将生成的查询存储在变量中,然后使用EXECUTE
(或EXECUTE IMMEDIATE
)语句执行它们,这是使用here的方法(参见右侧窗格),但Postgres赢了&#39 ;让我在一个函数之外声明一个变量,我一直在试着如何将它组合在一起,无论这个方向是否遵循,或许还有更简单的东西。
您是否有任何指示,我目前正在尝试这样的事情,受到other question的启发,但不知道我是否朝着正确的方向前进:
CREATE OR REPLACE FUNCTION foo()
RETURNS void AS
$$
DECLARE
dyn_sql text;
BEGIN
dyn_sql := SELECT 'SELECT min('||column_name||') from salesdata'
FROM information_schema.columns
WHERE table_name = 'salesdata';
execute dyn_sql
END
$$ LANGUAGE PLPGSQL;
答案 0 :(得分:4)
在您自己推出之前,请查看系统表pg_statistic
或视图pg_stats
:
此视图仅允许访问对应的pg_statistic行 用户有权阅读的表格,因此是安全的 允许对此视图进行公共读取访问。
它可能已经有一些您要计算的统计数据。它由ANALYZE
填充,因此您可以在检查之前为新(或任何)表运行它。
-- ANALYZE tbl; -- optionally, to init / refresh
SELECT * FROM pg_stats
WHERE tablename = 'tbl'
AND schemaname = 'public';
似乎您想要返回给定表中每列的最小值。这不是一项简单的任务,因为函数(如一般的SQL)要求在创建时知道返回类型 - 或者至少在调用时借助多态数据类型
此功能可自动安全地完成所有操作。适用于任何表,只要每列允许聚合函数min()
。但是你需要知道你对plpgsql的看法。
CREATE OR REPLACE FUNCTION f_min_of(_tbl anyelement)
RETURNS SETOF anyelement AS
$func$
BEGIN
RETURN QUERY EXECUTE (
SELECT format('SELECT (t::%2$s).* FROM (SELECT min(%1$s) FROM %2$s) t'
, string_agg(quote_ident(attname), '), min(' ORDER BY attnum)
, pg_typeof(_tbl)::text)
FROM pg_attribute
WHERE attrelid = pg_typeof(_tbl)::text::regclass
AND NOT attisdropped -- no dropped (dead) columns
AND attnum > 0 -- no system columns
);
END
$func$ LANGUAGE plpgsql;
呼叫:
SELECT * FROM f_min_of(NULL::tbl); -- tbl being the table name
您需要了解这些概念:
EXECUTE
的plpgsql中的动态SQL。相关答案详细解释:
我正在利用为每个现有表定义行类型的Postgres。使用多态类型的概念,我能够创建适用于任何表的一个函数。
但是,与基础列相比,某些聚合函数返回相关但不同的数据类型。例如,min(varchar_column)
返回text
,它与位兼容,但不是完全相同的数据类型。 plpgsql函数在这里有一个弱点,并坚持在RETURNS
子句中声明的数据类型完全。没有尝试施放,甚至不是隐式演员,也不是说任务演员。
应该改进。用Postgres 9.3测试。没有用9.4重新测试,但我很确定,这方面没有任何改变。
这就是这个结构的用武之地:
SELECT (t::tbl).* FROM (SELECT ... FROM tbl) t;
起初似乎扭曲了。这是解决方法:通过将整行强制转换为基础表的行类型,我们强制赋值转换为每列提供原始数据类型。
请注意,某些聚合函数可能会失败。 sum()
为numeric
返回sum(bigint_column)
以容纳溢出基本数据类型的总和。回到bigint
可能会失败......
答案 1 :(得分:0)
另外,由于强调了数据类型的重要性,我有点期待在某些时候抛出一个扳手,我主要担心的是如何自动生成查询及其执行,最后一点是我的主要关注点。
我已经尝试过你提供的功能(我可能需要开始学习一些plpgsql)但是在SELECT(t :: tbl)处出错:
ERROR: type "tbl" does not exist
顺便问一下,在python中这是什么(t :: abc)表示法,这将是一个列表切片,但在PLPGSQL中可能不是这样的