Oracle:计算表中每列的非空字段

时间:2017-06-28 10:49:35

标签: sql oracle

我需要一个查询来计算表中每个列的非空值的总数。由于我的表有数百列,我正在寻找一个只需要输入表名的解决方案。

也许使用以下结果:

select COLUMN_NAME from ALL_TAB_COLUMNS where TABLE_NAME='ORDERS';

获取列名,然后使用子查询为每个列名添加计数?另外一个复杂因素是我只对DB进行只读访问,因此我无法创建任何临时表。

稍微退出我的联赛,所以任何帮助都表示赞赏。

4 个答案:

答案 0 :(得分:1)

在SQL中构建查询或使用电子表格。然后运行查询。

例如,假设您的列名很简单且没有特殊字符:

select replace('select ''[col]'', count([col]) from orders union all ',
               '[col]', COLUMN_NAME
              ) as sql
from ALL_TAB_COLUMNS
where TABLE_NAME = 'ORDERS';

(当然,这可以适用于更复杂的列名,但我试图表明这个想法。)

然后复制代码,删除最终的union all并运行它。

如果没有太多列,您可以将其放在一个字符串中:

select listagg(replace('select ''[col]'', count([col]) from orders',
                       '[col]', COLUMN_NAME
                      ), ' union all '
               ) within group (order by column_name) as sql
from ALL_TAB_COLUMNS
where TABLE_NAME = 'ORDERS';

你也可以使用execute immediate使用相同的查询,但这似乎有点过分。

答案 1 :(得分:0)

如果您对结果row-ar而不是column-ar感到满意:

SELECT 'SELECT ''dummy'', 0 FROM DUAL' FROM DUAL
UNION ALL 
SELECT 
  ' UNION ALL SELECT ''' || 
  column_name ||
  ''', COUNT(' || 
  column_name || 
  ') FROM ' || 
  TABLE_NAME
FROM 
  all_tab_columns
WHERE 
  table_name = 'ORDERS'

这是一个编写SQL"的SQL。然后你可以复制并运行以获得你的答案。应该使结果集看起来像:

  

SELECT' dummy',0 FROM dual

     

UNION ALL SELECT' col1',COUNT(col1)FROM ORDERS

     

UNION ALL SELECT' col2',COUNT(col2)FROM ORDERS

     

...

如果您想要结果列-ar:

SELECT 'SELECT '
UNION ALL
SELECT 
  'COUNT(' || 
  column_name ||
  ') as count_' || 
  column_name || 
  ', ' || 
  TABLE_NAME
FROM 
  all_tab_columns
WHERE 
  table_name = 'ORDERS'
UNION ALL
SELECT 'null as dummy_column FROM ORDERS'

应该使结果集看起来像:

  

选择

     

COUNT(col1)as count_col1,

     

COUNT(col2)as count_col2,

     

...

     

null as dummycoll FROM orders

警告:我没有安装oracle,我可以测试这些,它是从内存写的,可能需要一些调试

答案 2 :(得分:0)

这将生成SQL以获取列中的计数,并将使用非字母数字字符处理区分大小写的列名和列名:

SELECT 'SELECT '
       || LISTAGG(
         'COUNT("' || column_name || '") AS "' || column_name || '"',
         ', '
       ) WITHIN GROUP ( ORDER BY column_id )
       || ' FROM "' || table_name || '"' AS sql
FROM   ALL_TAB_COLUMNS
WHERE  TABLE_NAME = 'ORDERS'
GROUP BY TABLE_NAME;

或者,如果您有大量列生成超过4000个字符的字符串,则可以使用custom aggregation function to aggregate VARCHAR2s into a CLOB然后执行:

SELECT 'SELECT '
       || CLOBAgg( 'COUNT("' || column_name || '") AS "' || column_name || '"' )
       || ' FROM "' || table_name || '"' AS sql
FROM   ALL_TAB_COLUMNS
WHERE  TABLE_NAME = 'ORDERS'
GROUP BY TABLE_NAME;

答案 3 :(得分:0)

在 Oracle 19 中(我在 Ora 12 中使用了类似的代码,也许也可以),这无需生成另一个要执行的选择:

select * from
(
    select table_name, column_name,
           to_number( extractvalue( xmltype(dbms_xmlgen.getxml('select count(to_char(substr('||column_name||',1,1))) c from '||table_name)) ,'/ROWSET/ROW/C')) count
    from all_tab_columns where owner = user
) 
--where table_name = 'MY_TABLE'
;

它将创建带有计数的 XML,从中提取当前计数。这里的 substr 和 to_char 函数用于提取第一个字符,因此它也适用于 CLOB 列