如何计算每列中存在多少个空值?

时间:2019-04-30 14:03:51

标签: sql oracle oracle10g

我有一个这样的表A:

col1 col2 {{1 }}
col3 1 0
null null null
null 3 null
null null 5

我想要在 Oracle 10G 中输出如下内容:

1 column_name
null_count col1
2 col2
2 col3

我已经使用 UNION ALL 做到了这一点:

         3

工作正常,但要花很多时间,因为有近100个 UNION ALL 。我想在不使用 UNION ALL 的情况下实现相同的输出。

  

是否可以通过不使用 UNION ALL 来实现这一目标?

3 个答案:

答案 0 :(得分:1)

您可以为此使用UNPIVOT(我不确定古老的Oracle 10是否已支持该功能-十多年来我一直没有使用它)

select colname, count(*) - count(val) as num_nulls
from t1
  UNPIVOT include nulls 
      (val for colname in (col1 as 'C1', 
                           col2 as 'C2', 
                           col3 as 'C3'))
group by colname
order by colname; 

不确定那是否更快。

在线示例:https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=4e807b8b2d8080abac36574f776dbf04

答案 1 :(得分:0)

我会推荐此查询:

SELECT 'col1' AS col_name, COUNT(*) - COUNT(col1) AS col_null_count FROM t UNION ALL
SELECT 'col2' AS col_name, COUNT(*) - COUNT(col2) AS col_null_count FROM t UNION ALL
SELECT 'col3' AS col_name, COUNT(*) - COUNT(col3) AS col_null_count FROM t

但是您可以尝试这样写:

WITH cte AS (
    -- 1 rows by n columns
    SELECT COUNT(*) - COUNT(col1) AS col1_null_count
         , COUNT(*) - COUNT(col2) AS col2_null_count
         , COUNT(*) - COUNT(col3) AS col3_null_count
    FROM t
)
-- n rows by 2 columns
SELECT 'col1' AS col_name, col1_null_count AS col_null_count FROM cte UNION ALL
SELECT 'col2' AS col_name, col2_null_count AS col_null_count FROM cte UNION ALL
SELECT 'col3' AS col_name, col3_null_count AS col_null_count FROM cte

答案 2 :(得分:0)

Oracle 10g不支持UNPIVOT和PIVOT运算符,因此要执行10g中的操作,您需要使用伪表(包含与未透视表相同的行数) ,即3),就像这样:

WITH your_table AS (SELECT 1 col1, 0 col2, NULL col3 FROM dual UNION ALL
                    SELECT NULL col1, NULL col2, NULL col3 FROM dual UNION ALL
                    SELECT 3 col1, NULL col2, NULL col3 FROM dual UNION ALL
                    SELECT NULL col1, 5 col2, 1 col3 FROM dual)
SELECT CASE WHEN dummy.id = 1 THEN 'col1'
            WHEN dummy.id = 2 THEN 'col2'
            WHEN dummy.id = 3 THEN 'col3'
       END column_name,
       COUNT(CASE WHEN dummy.id = 1 THEN CASE WHEN col1 IS NULL THEN 1 END
                  WHEN dummy.id = 2 THEN CASE WHEN col2 IS NULL THEN 1 END
                  WHEN dummy.id = 3 THEN CASE WHEN col3 IS NULL THEN 1 END
             END) null_count
FROM   your_table
       CROSS JOIN (SELECT LEVEL ID
                   FROM   dual
                   CONNECT BY LEVEL <= 3) dummy
GROUP BY dummy.id;

COLUMN_NAME NULL_COUNT
----------- ----------
col1                 2
col2                 2
col3                 3

如果您认为写大量列会花费很多时间,则始终可以编写一个查询,该查询将自己生成大量case语句,例如:

SELECT 'when dummy.id = '||row_number() OVER (PARTITION BY owner, table_name ORDER BY column_id)||' then '''||LOWER(column_name)||'''' first_part,
       'when dummy.id = '||row_number() OVER (PARTITION BY owner, table_name ORDER BY column_id)||' then case when '||column_name||' is null then 1 end' second_part
FROM   all_tab_columns a
WHERE  owner = ...
AND    table_name = ...
-- and column_name in (...)
ORDER BY column_id;

(我包括了row_number()分析函数,而不是使用column_id,因为如果要排除某些列,column_id列将不再是从1开始的连续数字。)