Truy vấn nào sẽ trả về tên của các cột trong bảng có tất cả các hàng là NULL?
Truy vấn nào sẽ trả về tên của các cột trong bảng có tất cả các hàng là NULL?
Câu trả lời:
thử nghiệm:
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;
chức năng:
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;$$;
truy vấn:
select table_schema, table_name, column_name,
has_nonnulls(table_schema, table_name, column_name)
from information_schema.columns
where table_schema='stack';
kết quả:
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)
Ngoài ra, bạn có thể nhận được câu trả lời gần đúng bằng cách truy vấn danh mục - nếu null_frac
bằng 0 cho biết không có giá trị nào nhưng phải được kiểm tra hai lần đối với dữ liệu 'thực':
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
nếu chúng trống khi tạo bảng. Tôi tìm thấy điều này ngày hôm nay khi làm một số vệ sinh. Tôi phát hiện ra rằng một số bảng khát vọng lịch sử đã được nhập khẩu bằng cách sử dụng ogr2ogr
. nếu không có cột không gian trong dữ liệu được nhập, hãy ogr2ogr
tạo một cột hình học đầy đủ <NULL>
. My pg_stats
không có các cột hình học từ các bảng tham vọng đã nhập (nó có tất cả các cột khác cho các bảng đó). Khá kỳ lạ, tôi nghĩ.
Trong Postgresql, bạn có thể lấy dữ liệu trực tiếp từ số liệu thống kê:
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;
Bạn có thể nhận được một vài thông tin sai, vì vậy hãy kiểm tra lại theo thứ tự sau khi tìm thấy các ứng cử viên.
null_frac=1
?
Tôi sẽ chỉ cho bạn giải pháp của tôi trong T-SQL, hoạt động cho SQL Server 2008. Tôi không quen với PostgreQuery, nhưng tôi hy vọng rằng bạn sẽ tìm thấy một số hướng dẫn trong giải pháp của mình.
-- 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);
Tóm lại, những gì tôi đã làm là tạo một bảng thử nghiệm với 5 cột, ID và testTime được tạo bởi hàm nhận dạng và hàm getdate (), trong khi 3 cột varchar là những cột được quan tâm. Một cái sẽ chỉ có các giá trị NULL, một cái sẽ không có bất kỳ NULL nào, cái còn lại sẽ là một cột kết hợp. Kết quả cuối cùng của tập lệnh sẽ là tập lệnh sẽ báo cáo cột nullColumn là có tất cả các hàng NULL.
Ý tưởng là tính toán hàm DATALENGTH cho mỗi cột (tính toán số byte cho một biểu thức đã cho). Vì vậy, tôi đã tính giá trị DATALENGTH cho mỗi hàng của mỗi cột và tạo SUM cho mỗi cột. Nếu SUM trên mỗi cột là NULL, thì cột hoàn chỉnh có các hàng NULL, nếu không thì có một số dữ liệu bên trong.
Bây giờ bạn phải tìm bản dịch cho PostgreSQL và hy vọng một đồng nghiệp sẽ có thể giúp bạn điều đó. Hoặc có thể có một chế độ xem hệ thống đẹp sẽ cho thấy tôi ngu ngốc như thế nào khi phát minh lại bánh xe :-).
Bạn cần truy vấn danh mục thông tin để biết thông tin đó:
SELECT column_name FROM information_schema.columns WHERE table_name='your_table'
cung cấp cho bạn các bảng phù hợp cho các cột của bạn.
Tôi không có cài đặt postgres hiện tại trong tay nhưng phần còn lại nên đơn giản
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
Sau khi kết hợp từ một số tài nguyên, tôi đã đưa ra hàm và truy vấn này để tìm tất cả các cột trống trong tất cả các bảng cơ sở dữ liệu
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))
Thưởng thức :)