Пошук порожніх стовпців таблиці в PostgreSQL


17

Який запит повертає назву стовпців таблиці, де всі рядки NULL?


Ви маєте на увазі конкретну таблицю або всі таблиці в схемі?
Джек Дуглас

1
Навіщо вам це потрібно робити? Здається, що у вас занадто багато стовпців / таблиць і слід переосмислити свій дизайн.
eevar

Відповіді:


13

тестова площадка:

create role stack;
create schema authorization stack;
set role stack;

create table my_table as 
select generate_series(0,9) as id, 1 as val1, null::integer as val2;

create table my_table2 as 
select generate_series(0,9) as id, 1 as val1, null::integer as val2, 3 as val3;

функція:

create function has_nonnulls(p_schema in text, p_table in text, p_column in text)
                returns boolean language plpgsql as $$
declare 
  b boolean;
begin
  execute 'select exists(select * from '||
          p_table||' where '||p_column||' is not null)' into b;
  return b;
end;$$;

запит:

select table_schema, table_name, column_name, 
       has_nonnulls(table_schema, table_name, column_name)
from information_schema.columns
where table_schema='stack';

результат:

 table_schema | table_name | column_name | has_nonnulls
--------------+------------+-------------+--------------
 stack        | my_table   | id          | t
 stack        | my_table   | val1        | t
 stack        | my_table   | val2        | f
 stack        | my_table2  | id          | t
 stack        | my_table2  | val1        | t
 stack        | my_table2  | val2        | f
 stack        | my_table2  | val3        | t
(7 rows)

Крім того, ви можете отримати приблизну відповідь, запитуючи каталог - якщо null_fracнуль означає, що немає нулів, але його слід двічі перевірити на "реальні" дані:

select tablename, attname, null_frac from pg_stats where schemaname='stack';

 tablename | attname | null_frac
-----------+---------+-----------
 my_table  | id      |         0
 my_table  | val1    |         0
 my_table  | val2    |         1
 my_table2 | id      |         0
 my_table2 | val1    |         0
 my_table2 | val2    |         1
 my_table2 | val3    |         0
(7 rows)

1
Це старе питання привіт, але люди, які використовують просторові розширення (postgis), повинні зазначити, що порожні просторові стовпці не відображаються, pg_statsякщо вони є порожніми під час створення таблиці. Я дізнався це сьогодні, коли займався домашнім господарством. Я виявив, що деякі історичні просторі таблиці були імпортовані за допомогою ogr2ogr. якщо в імпортованих даних немає просторового стовпця, ogr2ogrстворюється повний стовпчик геометрії <NULL>. У моїх pg_statsнемає стовпців геометрії з імпортованих додаткових таблиць (у них є всі інші стовпці для цих таблиць). Досить дивно, подумав я.
GT.

6

У Postgresql ви можете отримати дані безпосередньо зі статистики:

vacuum analyze; -- if needed

select schemaname, tablename, attname
from pg_stats
where most_common_vals is null
and most_common_freqs is null
and histogram_bounds is null
and correlation is null
and null_frac = 1;

Можливо, ви отримаєте декілька помилкових позитивних результатів, тому перевірте перевірку після пошуку кандидатів.


Чи потрібні вам інші умови, ніж null_frac=1?
Джек Дуглас

Я не впевнений. null_frac, мабуть, справжній, тому може статися, що він округляє 1 до деяких випадкових випадків. Але навіть з 1 з 10k рядків це призведе до того, що підходить.
Дені де Бернарді,

1

Я покажу вам своє рішення в T-SQL, що працює для SQL Server 2008. Я не знайомий з PostgreSQL, але сподіваюся, що ви знайдете вказівки щодо мого рішення.

-- create test table
IF object_id ('dbo.TestTable') is not null
    DROP table testTable
go
create table testTable (
    id int identity primary key clustered,
    nullColumn varchar(100) NULL,
    notNullColumn varchar(100) not null,
    combinedColumn varchar(100) NULL,
    testTime datetime default getdate()
);
go

-- insert test data:
INSERT INTO testTable(nullColumn, notNullColumn, combinedColumn)
SELECT NULL, 'Test', 'Combination'
from sys.objects
union all
SELECT NULL, 'Test2', NULL
from sys.objects

select *
from testTable

-- FIXED SCRIPT FOR KNOWN TABLE (known structure) - find all completely NULL columns
select sum(datalength(id)) as SumColLength,
    'id' as ColumnName
from dbo.testTable
UNION ALL
select sum(datalength(nullColumn)) as SumColLength,
    'nullColumn' as ColumnName
from dbo.testTable
UNION ALL
select sum(datalength(notNullColumn)) as SumColLength,
    'notNullColumn' as ColumnName
from dbo.testTable
UNION ALL
select sum(datalength(combinedColumn)) as SumColLength,
    'combinedColumn' as ColumnName
from dbo.testTable
UNION ALL
select sum(datalength(testTime)) as SumColLength,
    'testTime' as ColumnName
from dbo.testTable

-- DYNAMIC SCRIPT (unknown structure) - find all completely NULL columns
declare @sql varchar(max) = '', @tableName sysname = 'testTable';

SELECT @sql +=
        'select sum(datalength(' + c.COLUMN_NAME + ')) as SumColLength,
    ''' + c.COLUMN_NAME + ''' as ColumnName
from ' + c.TABLE_SCHEMA + '.' + c.TABLE_NAME --as StatementToExecute
+ '
UNION ALL
'
FROM INFORMATION_SCHEMA.COLUMNS c
WHERE c.TABLE_NAME = @tableName;

SET @sql = left(@sql, len(@sql)-11)
print @sql;
exec (@sql);

Одним словом, я створив тестову таблицю з 5 стовпцями, ID та testTime, що генеруються ідентифікацією та функцією getdate (), при цьому цікавлять 3 колони varchar. Один матиме лише значення NULL, один не матиме NULL, інший - комбінований стовпець. Кінцевим результатом сценарію буде те, що сценарій повідомляє стовпець nullColumn як такий, що має всі рядки NULL.

Ідея полягала в тому, щоб обчислити функцію DATALENGTH для кожного стовпця (обчислює кількість байтів для заданого виразу). Тому я обчислив значення DATALENGTH для кожного рядка кожного стовпця і зробив SUM на стовпець. Якщо SUM на стовпець - NULL, то у повному стовпці є NULL рядків, інакше всередині є деякі дані.

Тепер ви повинні знайти переклад для PostgreSQL, і, сподіваємось, колега зможе вам у цьому допомогти. А може, є приємний вигляд системи, який покаже, наскільки я німий за винахід колеса :-).


1

Потрібно запитати в інформаційному каталозі таку інформацію:

SELECT column_name FROM information_schema.columns WHERE table_name='your_table'

дає таблиці відповідності для ваших стовпців.

Наразі у мене немає встановлення postgres, але все інше повинно бути простим

   loop over the results of the above query and foreach result
        send a COUNT(*) to the table
        if the count is null, give back the column,
                 else ignore it
   end foreach

Це працює, але це ітеративний підхід :-). Я віддаю перевагу встановленому підходу.
Маріан

0

Поєднавши декілька ресурсів, я придумав цю функцію та запит, щоб знайти всі порожні стовпці у всіх таблицях бази даних

CREATE OR REPLACE FUNCTION public.isEmptyColumn(IN table_name varchar, IN column_name varchar)
RETURNS boolean AS $$
declare 
    count integer;
BEGIN
    execute FORMAT('SELECT COUNT(*) from %s WHERE %s IS NOT NULL', table_name, quote_ident(column_name)) into count;
    RETURN (count = 0);
END; $$
LANGUAGE PLPGSQL; 


SELECT s.table_name, s.column_name
FROM information_schema.columns s
WHERE (s.table_schema LIKE 'public') AND
      (s.table_name NOT LIKE 'pg_%') AND
      (public.isEmptyColumn(s.table_name, s.column_name))

Насолоджуйтесь :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.