【问题标题】:How to calculate how many null values are present in each column?如何计算每列中有多少个空值?
【发布时间】:2019-04-30 14:03:51
【问题描述】:

我有一张这样的桌子:

col1col2col3
1 0null
null nullnull
3nullnull
null 5 1

我希望在 Oracle 10G 中得到这样的输出:

column_namenull_count
col1 2
col2 2
col3 @ 987654343@

我使用 UNION ALL 实现了这一点,如下所示:

select "col1" column_name,sum(case when col1 is null then 1 else 0 end) as null_count from A group by "col1"
union all
select "col2" column_name,sum(case when col2 is null then 1 else 0 end) as null_count from A group by "col2"
union all
select "col3" column_name,sum(case when col3 is null then 1 else 0 end) as null_count from A group by "col3";

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

有什么方法可以在不使用 UNION ALL 的情况下实现这一点?

【问题讨论】:

    标签: sql oracle oracle10g


    【解决方案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

    【讨论】:

    • 谢谢,这正是我要找的。​​span>
    • 但是当列的数据类型不同时会引起问题。
    【解决方案2】:

    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
    

    如果您认为编写大量列需要很长时间,您始终可以编写一个自己生成大量案例语句的查询,例如:

    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 开始的连续数字。)

    【讨论】:

      猜你喜欢
      • 2015-01-17
      • 2019-07-24
      • 2018-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-24
      • 2011-07-28
      • 2019-04-30
      相关资源
      最近更新 更多