2011-01-07 30 views
6

Tengo una tabla con muchas columnas y una columna de tipo.Oracle: Encontrar columnas con solo valores nulos

Algunas columnas parecen estar siempre vacías para un tipo específico.

Quiero crear una vista para cada tipo y solo mostrar las columnas relevantes para cada tipo. Trabajando bajo el supuesto de que si una columna tiene SOLAMENTE valores nulos para un tipo específico, entonces esas columnas no deberían formar parte de la vista, ¿cómo puede averiguarlo con las consultas?

¿Existe un SELECT [columnName] de [tabla] Donde [columnValues] ¿Son todos [nula]

Sé que completamente hecho todo lo alto ... Sólo estoy tratando de conseguir la idea a través de. ¡Gracias de antemano!

+0

Así que si usted tiene 50 columnas y 10 de ellos contienen sólo valores NULL, que desea una consulta que sólo se regreso las 40 columnas que tienen datos en realidad? ¿Y presumiblemente si uno de los otros 10 adquiere un valor, su consulta devolvería 41 columnas? – MartW

+0

Parece que tiene diferentes "tipos" o "tipos" de registros en la misma tabla, donde le gustaría tener una vista separada para cada uno. ¿Hay una columna que identifica el "tipo" del registro? –

+0

Sí, es correcto @CodeByMoonlight. –

Respuesta

0

¿Algo como esto?

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

Obviamente, se puede usar esa en un comunicado CREATE VIEW... si lo desea así.

+1

Además de que esto no selecciona columnas, esto ni siquiera indica cuándo "[columnValues] es ALL [nulo]". Esto seleccionará un grupo de filas donde ciertas columnas (para esa fila) son nulas - esto no es información útil para determinar qué columnas son todas nulas – Gerrat

+0

@Gerrat, Oracle no tiene el concepto de una palabra clave 'ALL' en la cláusula de condición de a 'SELECT' (ver http://download.oracle.com/docs/cd/B13789_01/server.101/b10759/conditions.htm#g1077361). Si @Jorge desea crear vistas diferentes para cada "tipo", necesita determinar si el "tipo" se basa en un discriminador de columna o si existen columnas nulas específicas para todos los registros de ese tipo. Él parece estar confundiendo los dos métodos. –

+2

@BQ: Esto no se trata de una palabra clave 'ALL' mística. Se trata de lo que OP está tratando de conseguir. Creo que si vuelves a leer lo que está buscando, está bastante claro por el contexto que lo que persigue es básicamente: "Dame los nombres de columna de las columnas para las que CADA fila de esa columna es nula, para un tipo particular". ... así que su sql devuelve filas en lugar de nombres de columna, y las filas que da realmente no nos acercan a saber si TODAS las filas de esa columna son NULAS. Simplemente devuelve filas donde (cada columna en un conjunto dado de columnas) es NULA – Gerrat

0

Después de ver los comentarios de @Gerrat y @ BQ, creo que puedo obtener los detalles que necesito de la siguiente manera: Tengo una tabla heredada que tiene N tipos diferentes. Todos los tipos comparten columnas y tienen columnas exclusivas.

Puedo crear una vista para cada tipo con todas las columnas, luego usar all_tab_columns para obtener todos los nombres de columna donde "num_nulls" es menor que el número total de filas para ese tipo específico.

A partir de allí, debería ser fácil reunir las columnas que se utilizan para cada tipo y crear las vistas.

¿Pensamientos?

2
select 
    count(col_1), 
    count(col_2), 
    count(col_3) 
from 
    <table> 

vuelve el número de registros por columna tienen un valor no nulo (al menos en Oracle, que es.)

Por ejemplo

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; 

rendimientos

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

lo que indica que col_3 solo consta de nulos.

Esta idea se puede usar para crear la vista deseada.

La mesa ahora necesita también la 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; 

cual estando seleccionado retorna:

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 
+0

Eso es SQL estándar, no solo Oracle. También puede hacer: 'SELECT COUNT (col_1), COUNT (col_2), COUNT (col_3) [...] FROM SomeTable HAVING COUNT (*)> 0 AND (COUNT (col_1) = 0 OR COUNT (col_2) = 0 OR COUNT (col_3) = 0'. Eso ignora todas las tablas vacías y solo devuelve algo si al menos una de las pruebas las columnas solo tienen nulos. –

+0

Mi tabla tiene más de 300 columnas. No deseo contar con cada 300 veces –

+0

No quiero ningún registro de mi tabla original. Lo que necesito es una lista de nombres de columnas de mi tabla donde todos los registros para un tipo específico tienen solo valores nulos. –

0

Creo que se puede solucionar esto usando metaprogramming. Use un cursor para recorrer cada tipo y columna, y use 'no existe' para verificar si la columna está vacía. Por ejemplo:

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 

Disculpas si hay un error en la sintaxis en algún lugar, no tengo nada para comprobar esto.

9
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 
+1

Tuve que ejecutar las estadísticas primero 'DBMS_STATS.gather_database_stats();' y luego funcionó como un amuleto! Gracias;) – nathanvda

0

TableColumn SELECT, tablecolumn2, ... DE TABLENAME donde la columna no es nulo

Cuestiones relacionadas