Oracle:查找只有空值的列

Posted

技术标签:

【中文标题】Oracle:查找只有空值的列【英文标题】:Oracle: Finding Columns with only null values 【发布时间】:2011-01-07 16:46:01 【问题描述】:

我有一个包含很多列和一个类型列的表。

对于特定类型,某些列似乎总是为空。

我想为每种类型创建一个视图,并且只显示每种类型的相关列。假设如果一列仅具有特定类型的空值,那么该列不应该是视图的一部分,您如何通过查询找到它?

有没有 SELECT [columnName] FROM [table] WHERE [columnValues] 都是 [null]

我知道我完全在上面做了这一切......我只是想把这个想法传达出去。 提前致谢!

【问题讨论】:

因此,如果您有 50 列,其中 10 列仅包含 NULL 值,您想要一个仅返回实际包含数据的 40 列的查询?并且大概如果其他 10 个中的一个获得一个值,那么您的查询将返回 41 列? 听起来您在同一个表中有不同“种类”或“类型”的记录,您希望每个表都有一个单独的视图。是否有标识记录“类型”的列? 是的,这是正确的@CodeByMoonlight。 是的@Adam Hawkes。我有一个名为“类型”的列,我想为每个单独的视图创建一个视图,同时消除所有混乱。 【参考方案1】:
SELECT  t.column_name
FROM    user_tab_columns t
WHERE   t.nullable = 'Y'
        AND t.table_name = 'YOUR_TABLE_NAME'
        AND t.num_distinct = 0

【讨论】:

我必须先运行统计数据 DBMS_STATS.gather_database_stats(); 然后这就像一个魅力!谢谢;)【参考方案2】:
select
  count(col_1),
  count(col_2),
  count(col_3)
from
  <table>

返回每列有多少条记录具有非空值(至少在 Oracle 中是这样)

例如

drop table tq84_count_nulls;

create table tq84_count_nulls (
  col_1  varchar(50),
  col_2  number,
  col_3  date
);

insert into tq84_count_nulls values (null, null, null);
insert into tq84_count_nulls values ('xx', null, null);
insert into tq84_count_nulls values (null,   42, null);
insert into tq84_count_nulls values ('yy',   12, null);

select
  count(col_1),
  count(col_2),
  count(col_3)
from
  tq84_count_nulls;

返回

COUNT(COL_1) COUNT(COL_2) COUNT(COL_3)
------------ ------------ ------------
           2            2            0

表示 col_3 仅包含空值。

然后可以使用这个想法来创建所需的视图。

该表现在还需要 *group_id*:

drop table tq84_count_nulls;
create table tq84_count_nulls (
  col_1    varchar(50),
  col_2    number,
  col_3    date,
  group_id varchar(2)
);

insert into tq84_count_nulls values (null, null, null, 'a');
insert into tq84_count_nulls values ('xx', null, null, 'a');
insert into tq84_count_nulls values (null,   42, null, 'a');
insert into tq84_count_nulls values ('yy',   12, null, 'a');

insert into tq84_count_nulls values (null, null, null, 'b');
insert into tq84_count_nulls values (null, null, null, 'b');
insert into tq84_count_nulls values (null,   42, null, 'b');
insert into tq84_count_nulls values (null,   12, null, 'b');




create or replace view nulls_per_type as 
with n as (
  select
    count(col_1) col_1_count,
    count(col_2) col_2_count,
    count(col_3) col_3_count,
    group_id
  from
    tq84_count_nulls
  group by 
    group_id
),
o as (
select case col_1_count when 0 then 'COL_1 is always 0 for ' || group_id else null end u from n union all
select case col_2_count when 0 then 'COL_2 is always 0 for ' || group_id else null end u from n union all
select case col_3_count when 0 then 'COL_3 is always 0 for ' || group_id else null end u from n
)
select * from o where u is not null;

选定返回时:

select * from nulls_per_type;

COL_1 is always 0 for b
COL_3 is always 0 for a
COL_3 is always 0 for b

【讨论】:

这是标准 SQL,而不仅仅是 Oracle。你也可以这样做:SELECT COUNT(col_1), COUNT(col_2), COUNT(col_3) [...] FROM SomeTable HAVING COUNT(*) &gt; 0 AND (COUNT(col_1) = 0 OR COUNT(col_2) = 0 OR COUNT(col_3) = 0。这将忽略所有空表,并且仅在至少一个测试列中只有空值时才返回任何内容。 我的表有 300 多列。我不想指望每 300 次。 我不想要原始表中的任何记录。我需要的是我的表中的列名列表,其中特定类型的所有记录都只有空值。【参考方案3】:

查看@Gerrat 和@BQ 的cmets 后,我想我可以通过以下方式获得所需的详细信息:我有一个具有N 种不同类型的旧表。所有类型共享列,并具有独占列。

我可以为每种类型创建一个包含所有列的视图,然后使用all_tab_columns 获取“num_nulls”小于该特定类型总行数的所有列名。

从那里应该很容易收集用于每种类型的列并创建视图。

想法?

【讨论】:

【参考方案4】:

我认为您可以使用元编程来解决这个问题。使用游标遍历每个类型和列,并使用“不存在”检查该列是否为空。例如:

CREATE TABLE result_table (type VARCHAR(50), column VARCHAR(50))

CURSOR c IS
    SELECT COLUMN_NAME FROM ALL_TAB_COLS WHERE TABLE_NAME = &table_name;

CURSOR ct IS
    SELECT DISTINCT type_name FROM &table_name;

BEGIN

FOR t in ct
LOOP
    FOR r in c
    LOOP
        --If you're confused about how this works, replace 'EXECUTE IMMEDIATE'
        --with print or something and look at the output
        EXECUTE IMMEDIATE
            'INSERT INTO result_table SELECT ''' ||
                t.type_name || ''', ''' || r.COLUMN_NAME ||
                ''' FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM ' || 
                &table_name || ' WHERE t.type_name = ''' || t.type_name ||
                ''' AND ' || r.COLUMN_NAME || ' IS NOT NULL);';
    END LOOP
END LOOP

SELECT * FROM result_table

抱歉,如果某处的语法有错误,我没有什么要检查的。

【讨论】:

【参考方案5】:

您可以使用以下查询来识别:

select * from (select ascii(t.col2)+ascii(t.col4)+ascii(t.col1)+ascii(t.col3) col from test_null_col t)
where col is null;

而你想在这里删除空列行是查询:

delete from
(select ascii(t.col2)+ascii(t.col4)+ascii(t.col1)+ascii(t.col3) col from test_null_col t)
where col is null;

【讨论】:

【参考方案6】:

要查找具有空值的行,请使用“为空”条件。

select * from table_A where table_col1 is null;

要反过来,找到所有非空值的行,使用“不为空”条件:

select * from table_A where table_col1 is not null;

范围比较中的空值:

select * from table_A where table_col1 < 15 or table_col1 is null;

【讨论】:

【参考方案7】:

这样的?

SELECT column1, column2, column3 -- and so on
FROM tableA
WHERE columnX IS NULL
AND columnY IS NULL
AND columnZ IS NULL;

显然,如果您愿意,也可以在 CREATE VIEW... 语句中使用它。

【讨论】:

除了不选择列这一事实之外,它甚至无法判断“[columnValues] 何时为 ALL [null]”。这将选择一堆行,其中某些列(对于该行)为空 - 这不是确定哪些列全部为空的有用信息 @Gerrat,Oracle 在SELECT 的条件子句中没有ALL 关键字的概念(请参阅download.oracle.com/docs/cd/B13789_01/server.101/b10759/…)。如果@Jorge 想要为每个“类型”创建不同的视图,他需要确定“类型”是基于列鉴别器还是基于该类型所有记录的特定空列的存在。他似乎混淆了这两种方法。 @BQ:这不是关于神秘的ALL 关键字。这是关于 OP 想要得到的东西。我认为,如果您重新阅读他正在寻找的内容,从上下文中可以清楚地看出他所追求的基本上是:“给我列的列名,该列的每一行都为空,对于特定类型。” ...所以你的 sql 返回行而不是列名,它给出的行并不能真正让我们更接近知道该列的每一行是否为 NULL。它只是返回(给定列集中的每一列)为 NULL 的行 @BQ:执行操作要求的一种方法可能是存储过程: 1. 找到 type col 的不同值; 2. 从像 all_tab_columns 这样的元数据表中读取列名; 3. 找到每种类型具有任何非空值的所有列; 4. 使用动态 sql 和 (3) 中的列为每个 type 创建一个视图。 ...相当多的工作, @BC:我几乎同意你的所有观点。我在想象这个 OP,继承了一个具有几百列的遗留单片表,其中大部分为空,可能有 20 种类型,并且想要某种shortcut 方式在此表上生成一些报告。很容易,每行(对于某些类型)为 null 的某些 cols 将永远不会在其中包含值(这些 cols 与这些类型完全无关 - 因此视图不会改变)。他的要求并不实际,但手动完成也是 PITA。【参考方案8】:
SELECT tablecolumn, tablecolumn2, ... FROM TABLENAME
WHERE column IS NOT NULL

【讨论】:

以上是关于Oracle:查找只有空值的列的主要内容,如果未能解决你的问题,请参考以下文章

access 查询空值和null值的区别

如何在 Spark/Scala 中查找具有许多空值的列

在 oracle 中对具有空值的列求和

如何获取数据集中具有空值的列的总数? [复制]

在每个数据库的表中查找具有空值的列[关闭]

在 Oracle 中仅选择没有 Null 值的列