如何从具有非空值的表中选择列?

新手上路,请多包涵

我有一个包含数百个列的表,其中许多列是空的,我想要我的 select 语句,以便只返回那些包含值的列。这将帮助我更好地分析数据。就像是:

从表名中选择(非空列);

我想选择所有至少有一个非空值的列。

这可以做到吗?

原文由 Walker 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 679
2 个回答

看看统计信息,它可能对您有用:

 SQL> exec dbms_stats.gather_table_stats('SCOTT','EMP');

PL/SQL procedure successfully completed.

SQL> select num_rows from all_tables where owner='SCOTT' and table_name='EMP';

  NUM_ROWS
----------
        14

SQL> select column_name,nullable,num_distinct,num_nulls from all_tab_columns
  2  where owner='SCOTT' and table_name='EMP' order by column_id;

COLUMN_NAME                    N NUM_DISTINCT  NUM_NULLS
------------------------------ - ------------ ----------
EMPNO                          N           14          0
ENAME                          Y           14          0
JOB                            Y            5          0
MGR                            Y            6          1
HIREDATE                       Y           13          0
SAL                            Y           12          0
COMM                           Y            4         10
DEPTNO                         Y            3          0

8 rows selected.

例如,您可以检查是否 NUM_NULLS = NUM_ROWS 来识别“空”列。

参考: ALL_TAB_COLUMNSALL_TABLES

原文由 Egor Rogov 发布,翻译遵循 CC BY-SA 2.5 许可协议

此块确定表中的所有列,在动态 SQL 中循环它们并检查它们是否为空,然后构造非空查询的 DBMS 输出查询。

您所要做的就是运行返回的查询。

我已经排除了 PK 和 BLOB 列。显然,这在逐列遍历时非常慢,并且对于非常热的表来说并不是很好,因为数据可能变化得太快,但这对我来说很有效,因为我控制了开发环境中的流量。

 DECLARE
  l_table_name      VARCHAR2(255) := 'XXXX';
  l_counter         NUMBER;
  l_sql             CLOB;

BEGIN
  FOR r_col IN (SELECT *
                FROM user_tab_columns tab_col
                WHERE table_name = l_table_name
                AND data_type NOT IN ('BLOB')
                AND column_name NOT IN (SELECT column_name
                                        FROM user_cons_columns con_col
                                        JOIN user_constraints cons ON con_col.constraint_name = cons.constraint_name AND con_col.table_name = cons.table_name
                                        WHERE con_col.table_name = tab_col.table_name
                                        AND constraint_type = 'P')
                ORDER BY column_id)
  LOOP

    EXECUTE IMMEDIATE 'SELECT COUNT(1) FROM '||l_table_name||' WHERE '||r_col.column_name||' IS NOT NULL'
    INTO l_counter;

    IF l_counter > 0 THEN
      IF  l_sql IS NULL THEN
        l_sql := r_col.column_name;
      ELSE
        l_sql :=  l_sql||','||r_col.column_name;
      END IF;
    END IF;

  END LOOP;

  l_sql :=  'SELECT '||l_sql||CHR(10)
         ||'FROM '||l_table_name;

  ----------
  DBMS_OUTPUT.put_line(l_sql);
END;

原文由 m.jerwan 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进