Tìm các cột trống của bảng trong PostgreSQL


17

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?


Bạn có nghĩa là một bảng cụ thể, hoặc tất cả các bảng trong một lược đồ?
Jack Douglas

1
Tại sao bạn cần phải làm điều đó? Âm thanh như bạn có quá nhiều cột / bảng và nên suy nghĩ lại về thiết kế của bạn.
eevar

Câu trả lời:


13

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

1
Đây là một câu hỏi cũ, nhưng những người sử dụng các phần mở rộng không gian (postgis) nên lưu ý rằng các cột không gian trống sẽ không xuất hiện pg_statsnế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 ogr2ogrtạo một cột hình học đầy đủ <NULL>. My pg_statskhô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ĩ.
GT.

6

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.


Bạn có cần bất kỳ điều kiện khác hơn null_frac=1?
Jack Douglas

Tôi không chắc. null_frac có lẽ là một thực tế, vì vậy nó có thể làm tròn thành 1 trong một số trường hợp kỳ lạ. Nhưng ngay cả với 1 trên 10k hàng, nó sẽ dẫn đến kết quả phù hợp.
Denis de Bernardy

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


1

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

Điều này đang hoạt động, nhưng đó là một cách tiếp cận lặp đi lặp lại :-). Tôi thích cách tiếp cận dựa trên thiết lập.
Mary

0

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.