我正在尝试使用Postgres功能进行一些数据分析。我尝试过以下功能导致错误。因为我是数据库功能,程序等的新手。我发现很难解决这个问题。
实际工作:
我想遍历表中的所有列并执行数据分析,即字符列的Count,count distinct,nulls,not nulls。 Min,Max for Numeric&日期列。请协助
CREATE OR REPLACE FUNCTION data_profiling (TABLE_VALUE VARCHAR)
RETURNS TABLE (
col_value VARCHAR,
DISTINCT_COUNT INT
)
AS $$
DECLARE
var_c Varchar;
BEGIN
FOR var_c IN(SELECT c.column_name,c.table_name
FROM information_schema.columns c
WHERE lower(c.table_name) = TABLE_VALUE)
LOOP
RETURN QUERY EXECUTE 'SELECT ' || var_c ||' as col_name, count(distinct ' || var_c ||') as distinct_count
FROM ' || TABLE_VALUE || ' group by ' || var_c;
END LOOP;
END; $$
LANGUAGE 'plpgsql';
错误:
ERROR: structure of query does not match function result type
DETAIL: Returned type character(50) does not match expected type character varying in column 1.
CONTEXT: PL/pgSQL function data_profiling(character varying) line 10 at RETURN QUERY
答案 0 :(得分:1)
游标返回记录而不是varchar,您需要将声明更改为:
var_c record;
记录将包含与您在选择列表中包含列的字段一样多的字段,每个字段都可以通过列的名称引用。使用format()
函数生成动态SQL也更好。
count()
也会返回bigint
而不是int
。您还需要将您选择的列投射到varchar
,否则您无法返回,例如一个整数值作为第一列。
CREATE OR REPLACE FUNCTION data_profiling (table_value varchar)
RETURNS TABLE (col_value varchar, distinct_count bigint)
AS
$$
DECLARE
var_c record;
BEGIN
FOR var_c IN (SELECT c.table_schema, c.column_name,c.table_name
FROM information_schema.columns c
WHERE lower(c.table_name) = TABLE_VALUE
and c.table_schema = 'public')
LOOP
RETURN QUERY EXECUTE
format('SELECT %I::varchar, count(distinct %I) FROM %I.%I group by %I',
var_c.column_name, var_c.column_name, var_c.table_schema, var_c.table_name, var_c.column_name);
END LOOP;
END; $$
LANGUAGE plpgsql;
占位符%I
(大写i
)将在必要时负责正确引用列或表名称。您还应确保包含架构名称。
语言名称是标识符,不要将其放在单引号中。
您也不需要在生成的SQL中指定列别名,因为输出列的名称由returns table (..)
部分定义。这使得代码更容易阅读。
答案 1 :(得分:0)
您需要声明返回表的长度
RETURNS TABLE (
col_value VARCHAR(8000),
DISTINCT_COUNT INT