Yanıtlar:
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_frac
sı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)
pg_stats
kiş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, ogr2ogr
dolu bir geometri sütunu oluşturur <NULL>
. Benim pg_stats
iç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.
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.
null_frac=1
mı?
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 :-).
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
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 :)