如何获得表中所有列的计数(*)?使用PostgreSQL

时间:2018-10-31 16:22:06

标签: sql database postgresql navicat

我有一堆表,其中一些表有数百列。我需要为每一列获取非空值的计数,并且我一直在手动进行。我想找出一种方法来获取表中所有列的所有计数。我查了一下stackoverflow和google,但是找不到答案。

我试过了,但是每列只返回值1。我知道它只是在计算列数,而不是每列中的值。有什么建议吗?

select count(COLUMN_NAME)
from information_schema.columns
where table_schema = 'schema_name'
and table_name = 'table_name'
group by COLUMN_NAME

5 个答案:

答案 0 :(得分:4)

COUNT(column_name)始终为您提供NON NULL个值的计数。

创建一个像这样的通用函数,可以将模式名和表名作为参数。

在这里,我正在构造由UNION ALL连接在一起的select语句,每个语句返回column_name的值,并且它是动态执行时所有列的计数。

CREATE OR REPLACE FUNCTION public.get_count( TEXT, TEXT )
RETURNS  TABLE(t_column_name  TEXT, t_count BIGINT )
LANGUAGE plpgsql
AS $BODY$
DECLARE
p_schema        TEXT := $1;
p_tabname       TEXT := $2;
v_sql_statement TEXT;

BEGIN

SELECT STRING_AGG( 'SELECT ''' 
       || column_name 
       || ''',' 
       || ' count(' 
       || column_name 
       || ')  FROM ' 
       || table_schema 
       || '.' 
       || table_name 
         ,' UNION ALL ' ) INTO v_sql_statement
FROM   information_schema.columns 
WHERE  table_schema   = p_schema 
       AND table_name = p_tabname; 

    IF v_sql_statement IS NOT NULL THEN
     RETURN QUERY EXECUTE   v_sql_statement;
    END IF;
END
$BODY$;

执行

knayak=# select c.col, c.count from 
 public.get_count( 'public', 'employees' ) as c(col,count);
      col       | count
----------------+-------
 employee_id    |   107
 first_name     |   107
 last_name      |   107
 email          |   107
 phone_number   |   107
 hire_date      |   107
 job_id         |   107
 salary         |   107
 commission_pct |    35
 manager_id     |   106
 department_id  |   106
(11 rows)

答案 1 :(得分:0)

尝试

SELECT 
sum(case when column1 is not null then 1 else 0 end) as col1_not_null_count
sum(case when column2 is not null then 1 else 0 end) as col2_not_null_count
sum(case when column3 is not null then 1 else 0 end) as col3_not_null_count
FROM information_schema.columns
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'

答案 2 :(得分:0)

我发现做到这一点的最好方法是编写一个case语句,使列中的非null值变为1,而null变为0。然后,我对case求和以得到非空值:

SELECT SUM(CASE WHEN COLUMN_NAME1 IS NULL THEN 1 ELSE 0 END) AS COL1_COUNT
     , SUM(CASE WHEN COLUMN_NAME2 IS NULL THEN 1 ELSE 0 END) AS COL2_COUNT
  FROM TABLE_NAME

在您的选择中,我看到您正在查看information_schema.columns表。您可以通过对该表进行选择来动态生成以上代码:

SELECT ', SUM(CASE WHEN ' + column_name + ' IS NULL THEN 1 ELSE 0 END) AS ' + column_name + '_COUNT'
FROM information_schema.columns
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'

您还可以为相关表格中的每一列动态创建一个不同的选择:

SELECT 'SELECT SUM(CASE WHEN ' + column_name + ' IS NULL THEN 1 ELSE 0 END) AS ' + column_name + '_COUNT FROM ' + table_schema + '.' + table_name
FROM information_schema.columns
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'

答案 3 :(得分:0)

实际上并没有一种神奇的方法。如果需要检查100个不同的列中的每一个以查看有多少个非空值,则必须指定表中的每个列。

关于您能做的最好的事情就是使用系统目录来帮助您编写查询:

select 'SUM(CASE WHEN ' + column_name + ' IS NULL THEN 1 ELSE 0 END) AS ' + column_name
from information_schema.columns
where table_schema = 'schema_name'
    and table_name = 'table_name'
    and is_nullable = 'YES' 

如果列名中包含空格或其他特殊字符,则可能需要添加带引号的标识符。

然后,您可以将该输出复制到另一个查询,并添加查询的缺失部分。我添加了and is_nullable = 'YES',是因为浪费时间检查NOT NULL列。据我所知,该列存在于PostgreSQL中。

答案 4 :(得分:0)

我来到这里是为了回答同样的问题,但我想在不创建函数的情况下做到这一点,因为我并不总是有能力在我正在使用的数据库中做到这一点。但是我使用的数据库安装了 tblfunc 模块,该模块具有交叉表功能,将 sql 字符串作为输入。我能够生成可以在该函数中使用的 sql,以从任何表中获取所有列数。这是我使用的代码,我在其中输入了我想要的 schema_name 和 table_name:

select * from crosstab('select column_name, ''num'' as category, sum(num) from (' || (
    select
        string_agg(sql, '') as sql_string
    from (
        select
            case when row_number() OVER () = 1 then '' else ' union all ' end ||
            'select ''' || column_name || ''' as column_name, ' || 'count(' || column_name || ') as num from ' || table_schema || '.' || table_name as sql
        from information_schema.columns
        where table_schema = 'schema_name'
            and table_name = 'table_name') as sql_query limit 1 
    ) || ') as column_counts group by column_name, category') 
                        AS t(column_name text, num numeric) order by num asc