PostgreSQL'de bir tablonun boş sütunlarını bulma


17

Hangi sorgu, tüm satırların NULL olduğu bir tablonun sütunlarının adını döndürür?


Belirli bir tablo mu yoksa şemadaki tüm tablolar mı demek istediniz?
Jack Douglas

1
Bunu neden yapmanız gerekiyor? Çok fazla sütununuz / tablonuz var ve tasarımınızı yeniden düşünmelisiniz.
eevar

Yanıtlar:


13

test ortamı:

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;

fonksiyon:

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;$$;

sorgu:

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

sonuç:

 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)

Buna ek olarak, kataloğu sorgulayarak yaklaşık bir cevap alabilirsiniz - null_fracsıfır ise sıfır olmadığını gösterir ancak 'gerçek' verilere karşı iki kez kontrol edilmelidir:

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
Bu eski bir sorudur, ancak uzamsal uzantılar (postgis) kullanan pg_statskişiler, tablo oluşturmada boşlarsa boş uzamsal sütunların görünmediğini belirtmelidir. Bugün temizlik yaparken bunu öğrendim. Bazı tarihsel uzamsal tabloların ithal edildiğini keşfettim ogr2ogr. içe aktarılan verilerde uzamsal sütun yoksa, ogr2ogrdolu bir geometri sütunu oluşturur <NULL>. Benim pg_statsiçe aktarılan uzamsal tablolardan geometri sütunları yok (bu tablolar için diğer tüm sütunlara sahiptir). Oldukça tuhaf, diye düşündüm.
GT.

6

Postgresql'de, verileri doğrudan istatistiklerden alabilirsiniz:

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;

Birkaç yanlış pozitif alabilirsiniz, bu yüzden adayları bulduktan sonra tekrar kontrol etmek.


Başka koşullara ihtiyacınız var null_frac=1mı?
Jack Douglas

Emin değilim. null_frac muhtemelen gerçek, bu yüzden bazı garip durumlarda 1'e yuvarlanabilir. Ancak 10 bin satırdan 1'inde bile, bu uygun bir şeyle sonuçlanır.
Denis de Bernardy

1

Size T-SQL'deki çözümümü göstereceğim, SQL Server 2008 için çalışıyorum. PostgreSQL'e aşina değilim, ama umarım çözümümde bazı rehberler bulacaksınız.

-- 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);

Kısacası, 3 varchar sütun ilgilenen olanlar iken, kimlik ve getdate () işlevi tarafından oluşturulan, ID ve testTime 5 sütun, bir test tablosu oluşturmak oldu. Birinde yalnızca NULL değerler olacak, birinde NULL olmayacak, diğerinde birleştirilmiş sütun olacak. Komut dosyasının son sonucu, komut dosyasının nullColumn sütununu tüm NULL satırlarına sahip olarak raporlamasıdır.

Fikir, her sütun için DATALENGTH işlevini hesaplamaktı (belirli bir ifade için bayt sayısını hesaplar). Bu yüzden her sütunun her satırı için DATALENGTH değerini hesapladım ve sütun başına bir TOPLA yaptım. Sütun başına TOPLA NULL ise, tüm sütunda NULL satır bulunur, aksi takdirde içinde bazı veriler vardır.

Şimdi PostgreSQL için çeviriyi bulmak zorundasınız ve umarım bir meslektaşınız size bu konuda yardımcı olabilir. Ya da belki de tekerleği yeniden icat etmek için ne kadar aptal olduğumu gösterecek güzel bir sistem görünümü var :-).


1

Bu tür bilgiler için bilgi kataloğunu sorgulamanız gerekir:

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

sütunlarınız için eşleşen tabloları verir.

Şu anda elinizde bir postgres kurulumu yok, ancak geri kalanı basit olmalı

   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

Bu işe yarıyor, ama yinelemeli bir yaklaşım :-). Kümeye dayalı yaklaşımı tercih ederim.
Marian

0

Birkaç kaynaktan birleştirdikten sonra, tüm veritabanı tablolarındaki tüm boş sütunları bulmak için bu işlev ve sorgu ile geldim

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))

Zevk almak :)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.