使用PostgreSQL函数进行数据分析

时间:2016-11-02 19:25:28

标签: postgresql function plpgsql

我正在尝试使用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

2 个答案:

答案 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