2010-02-08 42 views
20

我有一個包含數百個列的表,其中許多列都是空的,我希望有我的select語句,以便只返回包含值的列。這將有助於我更好地分析數據。例如:如何從具有非空值的表中選擇列?

從tablename中選擇(非空列);

我想選擇至少有一個非空值的所有列。

可以這樣做嗎?

+0

你的問題很不清楚。正如所寫,它看起來像要求從表中選擇*所有*行?那實際上是你在追求什麼?或者,你的意思是包含一個WHERE子句,並且只選擇在感興趣的列中包含非NULL值的行?或者你是否想要選擇所有行都不可空的所有列?你能解釋一下嗎? – 2010-02-08 06:12:40

+5

我覺得這個問題很清楚。他只想選擇至少一行包含數據的列。當然,有WHERE子句會使這更加困難。 – Thilo 2010-02-08 06:14:22

+0

您想對數據做什麼?它將在哪裏使用? – shahkalpesh 2010-02-08 06:14:42

回答

3

看一看的統計信息,可能對您有用:

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

2

我不認爲這可以在一個查詢中完成。您可能需要一些plsql來首先測試哪些列包含數據並根據該信息將語句放在一起。當然,如果表中的數據發生變化,您必須重新創建語句。

declare 

    l_table   varchar2(30) := 'YOUR_TABLE'; 
    l_statement  varchar2(32767); 
    l_test_statement varchar2(32767); 

    l_contains_value pls_integer; 

    -- select column_names from your table 
    cursor c is 
     select column_name 
      ,nullable 
     from user_tab_columns 
     where table_name = l_table; 

begin 
    l_statement := 'select '; 
    for r in c 
    loop 
     -- If column is not nullable it will always contain a value 
     if r.nullable = 'N' 
     then 
     -- add column to select list. 
     l_statement := l_statement || r.column_name || ','; 
     else 
     -- check if there is a row that has a value for this column 
     begin 
      l_test_statement := 'select 1 from dual where exists (select 1 from ' || l_table || ' where ' || 
           r.column_name || ' is not null)'; 
      dbms_output.put_line(l_test_statement); 
      execute immediate l_test_statement 
       into l_contains_value; 


      -- Yes, add column to select list 
      l_statement := l_statement || r.column_name || ','; 
     exception 
      when no_data_found then 
       null; 
     end; 

     end if; 
    end loop; 

    -- create a select statement 
    l_statement := substr(l_statement, 1, length(l_statement) - 1) || ' from ' || l_table; 

end; 
-1

你要求做的是在整個結果的每一行建立一個依賴關係。這實際上是沒有你想要的。如果在一行中每列的值爲'0',那麼只要想想分支的結果 - 突然你的結果集的模式增長到包括所有以前「空」列。您實際上正在成倍增長'*'的壞處,現在您的結果集不僅僅依賴於表的元數據 - 但是您的整個結果集依賴於明文數據。

你想要做的只是選擇你想要的領域,而不會偏離這個簡單的計劃。

4
select column_name 
from user_tab_columns 
where table_name='Table_name' and num_nulls=0; 

下面是簡單的代碼來獲取非空列..

0
select rtrim (xmlagg (xmlelement (e, column_name || ',')).extract ('//text()'), ',') col 
from (select column_name 
from user_tab_columns 
where table_name='<table_name>' and low_value is not null) 
+1

請不要只寫代碼作爲答案。解釋它的功能和工作原理。 – 2014-12-15 08:31:58

2

使用如下:

SELECT * 
FROM information_schema.columns 
WHERE table_name = 'Table_Name' and is_nullable = 'NO' 

Table_Name必須進行相應的更換...

+1

SQL 2012完美無缺! – Raffaeu 2016-07-13 08:48:15

+0

僅僅因爲某列可以爲空,並不意味着它沒有數據。 – Seth 2018-03-01 21:52:15

相關問題