10

I have a table with a lot of columns and a type column.

Some columns seem to be always empty for a specific type.

I want to create a view for each type and only show the relevant columns for each type. Working under the assumption that if a column has ONLY null values for a specific type, then that columns should not be part of the view, how can you find that out with queries?

Is there a SELECT [columnName] FROM [table] WHERE [columnValues] ARE ALL [null]

I know I COMPLETELY made it all up above... I'm just trying to get the idea across. Thanks in advance!

4
  • So if you have 50 columns, and 10 of them contain only NULL values, you want a query that will only return the 40 columns which actually have data in? And presumably if one of the other 10 acquires a value, your query would then return 41 columns? Commented Jan 7, 2011 at 16:58
  • It sounds like you have different "kinds" or "types" of records in the same table, where you'd like to have a separate view for each one. Is there a column which identifies the "type" of the record? Commented Jan 7, 2011 at 20:46
  • Yes that is correct @CodeByMoonlight. Commented Jan 21, 2011 at 15:56
  • Yes @Adam Hawkes. I have a column called "Type" and I want to create a view for each separate one, while removing all clutter. Commented Jan 21, 2011 at 15:57

8 Answers 8

17
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
Sign up to request clarification or add additional context in comments.

1 Comment

I had to run the statistics first DBMS_STATS.gather_database_stats(); and then this worked like a charm! Thanks ;)
4
select
  count(col_1),
  count(col_2),
  count(col_3)
from
  <table>

returns how many records per column have a non-null value (at least in Oracle, that is.)

For example

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;

returns

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

indicating that col_3 consists of nulls only.

This idea can then be used to create the desired view.

The table now needs also the *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;

Which, when selected returns:

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

3 Comments

That is standard SQL, not just Oracle. You could also do: 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. That ignores all empty tables and only returns anything if at least one of the tested columns has only nulls in it.
My table has over 300 columns. I don't want to count on each 300 times.
I don't want any records from my original table. What I need is a list of column names from my table where all the records for a specific type have only null values.
0

After looking at @Gerrat and @BQ's comments, I thouht I could get the details I need in the following way: I have a legacy table that has N different types. All types share columns, and have exclusive columns.

I can create a view for each type with all columns, then use all_tab_columns to get all column names where the "num_nulls" is less than the total number of rows for that specific type.

From there it should be easy to gather columns that are used for each type and create the views.

Thoughts?

Comments

0

I think you can solve this using metaprogramming. Use a cursor to loop through each type and column, and use 'not exists' to check if the column is empty. For example:

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

Apologies if there's a mistake in the syntax somewhere, I have nothing to check this on.

Comments

0

You can identify by using the below query :

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;

And you want to delete null column rows here is query :

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;

Comments

0

To find rows that have a null-value, use the "is null" condition.

select * from table_A where table_col1 is null;

To do the reverse, and find all the rows with a non-null value, use the "is not null" condition:

select * from table_A where table_col1 is not null;

Nulls in range comparisons:

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

Comments

-1

Something like this?

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

Obviously, you can use that in a CREATE VIEW... statement if you like as well.

8 Comments

Beside the fact that this doesn't select columns, this doesn't even tell when "[columnValues] are ALL [null]". This will select a bunch of rows where certain columns (for that row) are null - this isn't useful information to determine which columns are all null
@Gerrat, Oracle has no concept of an ALL keyword in the condition clause of a SELECT (see download.oracle.com/docs/cd/B13789_01/server.101/b10759/…). If @Jorge wants to create different views for each 'type' he needs to determine if the 'type' is based on a column discriminator or by the presence of specific null columns for all records of that type. He seems to be confusing the two methods.
@BQ: This isn't about a mystic ALL keyword. It's about what OP is trying to get. I think if you re-read what he's looking for, it's pretty clear from context that what he's after is basically: "Give me the column names of columns for which EVERY row of that column is null, for a particular type." ...so your sql returns rows instead of column names, and the rows it gives don't really get us closer to knowing if EVERY row for that column is NULL. It's simply returning rows where (every column in a given set of columns) is NULL
@BQ: One way to do what op is asking could be a stored procedure that: 1. Found distinct values for the type col; 2. Read the column names from a metadata table like all_tab_columns; 3. Found all columns that had any non-null values for each type; 4. Created a view for each type using dynamic sql and the columns from (3). ...a fair bit of work,
@BC: I agree with you on pretty much everything. I'm imagining this OP, having inherited a legacy, monolithic table with a few hundred columns, most of which are mostly null, and maybe 20 types, and wanting some sort of shortcut way to generate some reports on this table. It could easily be that some of the cols which are null for every row (for certain types) will never have values in them (the cols are completely irrelevant for those types - so the views wouldn't change). What he's asking for isn't really practical, but doing it manually would be a PITA as well.
|
-1
SELECT tablecolumn, tablecolumn2, ... FROM TABLENAME
WHERE column IS NOT NULL

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.