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_fracnull이 아닌 '실제'데이터에 대해 다시 확인해야하는 0 인 경우 :

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은 테이블을 만들 때 빈 공간 열 이 비어 있으면 나타나지 않습니다 . 하우스 키핑을 할 때 오늘 이것을 발견했습니다. 일부 역사적인 aspatial 테이블을 사용하여 가져 왔음을 발견했습니다 ogr2ogr. 가져올 데이터에 공간 열이 없으면로 ogr2ogr가득 찬 형상 열을 만듭니다 <NULL>. 내가 pg_stats가져온 aspatial 테이블에서 어떤 형상 열이 없습니다 (이는 해당 테이블에 대한 다른 모든 열이 있습니다). 꽤 이상하다고 생각했다.
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로 반올림 될 수 있습니다. 그러나 10k 행 중 1 행이라도 적합한 결과가 발생합니다.
Denis de Bernardy

1

SQL Server 2008에서 일하는 T-SQL 솔루션을 보여 드리겠습니다. 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);

간단히 말해서, ID 및 testTime이 identity 및 getdate () 함수에 의해 생성되는 5 개의 열, 테스트 대상 테이블은 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

이것은 작동하지만 반복적 인 접근 방식입니다 :-). 나는 세트 기반 접근법을 선호합니다.
Marian

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

즐겨 :)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.