Поиск значений (например, NaN) в таблице по всем колонкам сразу

Коллеги, я видел похожие вопросы, но, думаю, вдруг что-то изменилось за те годы, которые прошли с тех пор, как они были заданы.

Есть таблица(-ы) со многими полями. Таблица может быть одна или их может быть много и мы можем их объединить по какому-то уникальному полю. Изначально задача была получить записи не содержащие NaN ни в одном из полей, но, на самом деле, вопрос шире - вместо NaN может быть любое значение.

То есть, если я ищу по одному полю, то, очевидно:

SELECT * FROM table_name
WHERE field_name != 'NaN'::NUMERIC;

Если я ищу по всем полям, то мне надо так или иначе явно указывать названия полей и таблиц. А вот нет чего-то такого:

SELECT * FROM table_name
WHERE table_name.* != 'NaN'::NUMERIC;

(Я знаю - это не работает)

То есть, либо перечислять названия полей вручную, либо с помощью скрипта получать названия и генерировать динамически, либо какие-то очень витиеватые (на мой взгляд) динамические запросы. Во всех этих случаях мне проще затащить все таблицы в pandas и легко и приятно избавится от NaN. Но вдруг можно легко и приятно, но через SQL?

Спасибо!


Ответы (1 шт):

Автор решения: ValNik

Пример:

create table test (val1 int,val2 int);
insert  into test values
 (1,2)
,(3,null)
,(null,4)
,(null,null)
;

Запрос

select *
    -- строки содержащие только null
  ,case when t.* is null then 1 else 0 end fIsNull
    -- строки не содержащие null
  ,case when t.* is not null then 1 else 0 end fIsNotNull
    -- строки содержащие не null значения
  ,case when not (t.* is null) then 1 else 0 end fIsNotIsNull
    -- строки содержащие null значения
  ,case when not (t.* is not null) then 1 else 0 end fIsNotIsNotNull
from test t

Результат

val1 val2 fIsNull fIsNotNull fIsNotIsNull fIsNotIsNotNull
1 2 0 1 1 0
3 null 0 0 1 1
null 4 0 0 1 1
null null 1 0 0 1

Для любопытства, с такими данными

insert  into test values
 (1,2)
,(3,null)
,(null,4)
,(null,null)
,('NaN'::numeric,null)
,('NaN'::numeric,2)
;

запрос

select *
  ,concat(t.*) ts
from test t
-- where strpos(concat(t.*),'NaN')=0

выдаст результат

val1 val2 ts
1 2 (1,2)
3 null (3,)
null 4 (,4)
null null (,)
NaN null (NaN,)
NaN 2 (NaN,2)
select *
from test t
where  t.* is not null and  strpos(concat(t.*),'NaN')=0
val1 val2
1 2
→ Ссылка