繁体   English   中英

计算表中每一列的空值

[英]Counting nulls for each column in table

我们想计算表中每列有多少空值。 列太多,无法一一进行,因此创建了以下 PLSQL 过程。

在该过程的第一部分,获取所有列名。 这很有效,因为 dbms_output 正确地列出了它们。

其次,查询将 null 值的计数插入变量“nullscount”中。 这部分不起作用,因为为此变量打印的 output 始终为 0,即使对于我们知道存在空值的列也是如此。

有谁知道如何正确处理第二部分?

非常感谢。

CREATE OR REPLACE PROCEDURE COUNTNULLS AS 
nullscount int;

BEGIN

for c in (select column_name from all_tab_columns where table_name = upper('gp'))
loop

select count(*) into nullscount from gp where c.column_name is null;

dbms_output.put_line(c.column_name||' '||nullscount);
end loop;
 
END COUNTNULLS;

你可以通过这样的一个查询来获得它:这个查询只扫描一次表:

DBFiddle: https://dbfiddle.uk/asgrCezT

select *
from xmltable(
        '/ROWSET/ROW/*'
        passing
        dbms_xmlgen.getxmltype(
            (
            select 
                'select '
              ||listagg('count(*)-count("'||column_name||'") as "'||column_name||'"',',')
              ||' from '||upper('gp')
            from user_tab_columns 
            where table_name = upper('gp')
            )
        )
        columns
            column_name varchar2(30) path './name()',
            cnt_nulls   int path '.'
        );

结果:

COLUMN_NAME                     CNT_NULLS
------------------------------ ----------
A                                       5
B                                       4
C                                       3

此查询中的动态 sql 使用(24 个字符 + 列名长度),因此它应该可以正常工作,例如平均列名长度 = 10 的 117 列。如果您需要更多,可以重写一下,例如:

select *
from xmltable(
        'let $cnt := /ROWSET/ROW/CNT
         for $r in /ROWSET/ROW/*[name() != "CNT"]
           return <R name="{$r/name()}"> {$cnt - $r} </R>'
        passing
        dbms_xmlgen.getxmltype(
            (
            select 
                'select count(*) CNT,'
              ||listagg('count("'||column_name||'") as "'||column_name||'"',',')
              ||' from '||upper('gp')
            from user_tab_columns 
            where table_name = upper('gp')
            )
        )
        columns
            column_name varchar2(30) path '@name',
            cnt_nulls   int path '.'
        );

c.column_name is never null because it's the content of the column "column_name" of the table "all_tab_columns" not the column of which name is the value of c.column_name, in table gp. 您必须使用动态查询和 EXECUTE IMMEDIATE 来实现您想要的。

create table gp (
    id                             number generated by default on null as identity 
                                   constraint gp_pk primary key,
    c1                             number,
    c2                             number,
    c3                             number,
    c4                             number,
    c5                             number
)
;

-- add some data with NULLS and numbers
DECLARE
BEGIN
  FOR r IN 1 .. 20 LOOP
    INSERT INTO gp (c1,c2,c3,c4,c5) VALUES 
    (CASE WHEN mod(r,2) = 0 THEN NULL ELSE mod(r,2) END
    ,CASE WHEN mod(r,3) = 0 THEN NULL ELSE mod(r,3) END
    ,CASE WHEN mod(r,4) = 0 THEN NULL ELSE mod(r,4) END
    ,CASE WHEN mod(r,5) = 0 THEN NULL ELSE mod(r,5) END
    ,5);
  END LOOP;
END;
/

-- check what is in the table
SELECT * FROM gp;

-- do count of each column
DECLARE
  l_colcount NUMBER;
  l_statement VARCHAR2(100) := 'SELECT COUNT(*) FROM $TABLE_NAME$ WHERE $COLUMN_NAME$ IS NULL';
BEGIN
  FOR r IN (SELECT column_name,table_name FROM user_tab_columns WHERE table_name = 'GP') LOOP
  
    EXECUTE IMMEDIATE REPLACE(REPLACE(l_statement,'$TABLE_NAME$',r.table_name),'$COLUMN_NAME$',r.column_name) INTO l_colcount;
    
    dbms_output.put_line('Table: '||r.table_name||', column'||r.column_name||', COUNT: '||l_colcount);
  END LOOP;
END;
/

Table created.

Statement processed.

Result Set 4
ID  C1  C2  C3  C4  C5
1   1   1   1   1   5
2    -  2   2   2   5
3   1    -  3   3   5
4    -  1    -  4   5
5   1   2   1    -  5
6    -   -  2   1   5
7   1   1   3   2   5
8    -  2    -  3   5
9   1    -  1   4   5
10   -  1   2    -  5
11  1   2   3   1   5
12   -   -   -  2   5
13  1   1   1   3   5
14   -  2   2   4   5
15  1    -  3    -  5
16   -  1    -  1   5
17  1   2   1   2   5
18   -   -  2   3   5
19  1   1   3   4   5
20   -  2    -   -  5

20 rows selected.

Statement processed.

Table: GP, columnID, COUNT: 0
Table: GP, columnC1, COUNT: 10
Table: GP, columnC2, COUNT: 6
Table: GP, columnC3, COUNT: 5
Table: GP, columnC4, COUNT: 4
Table: GP, columnC5, COUNT: 0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM