Подсчет нескольких нулевых значений в таблице

Я провел некоторое исследование, и по большей части ответы приемлемы для небольших таблиц. Я работаю с таблицей, в которой около 25 столбцов. Что я хочу сделать, так это подсчитать, сколько нулевых значений во всей таблице. Насколько я понимаю, count() будет считать строку, в которой условие истинно. Так, например, для таблицы «some_table» с 12 строками и следующего утверждения:

Select Count(*) from some_table 
where condition = true

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


person nmaybyte    schedule 22.10.2013    source источник


Ответы (2)


Может быть, что-то вроде этого?

Select
  sum(
    case when field1 is null then 1 else 0 end+
    case when field2 is null then 1 else 0 end+
    case when field3 is null then 1 else 0 end+
    ...
    case when fieldN is null then 1 else 0 end
  )
from
  some_table 
where
  condition = true
person Lajos Veres    schedule 22.10.2013
comment
Спасибо за быстрый ответ! Я думаю, что это может сделать это. Раньше у меня не было успеха с функцией case, но я думаю, что использовал ее неправильно. РЕДАКТИРОВАТЬ: я только что проверил это. Это сработает. Большое спасибо! - person nmaybyte; 22.10.2013

Попробуй это

DECLARE
   null_sum NUMBER := 0;
   null_count NUMBER;
BEGIN
   FOR aCol IN (SELECT COLUMN_NAME FROM USER_TAB_COLS WHERE TABLE_NAME = 'SOME_TABLE') LOOP
      EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM SOME_TABLE WHERE condition = true AND '||aCol.COLUMN_NAME||' IS NULL' INTO null_count;
      null_sum := null_sum + null_count;
   END LOOP;
   DBMS_OUTPUT.PUT_LINE('Table SOME_TABLE has '||null_sum||' NULLS');
END;

Вместо того, чтобы делать цикл для каждого столбца, вы можете написать один динамический оператор, используя пакет DBMS_SQL, но это требует больше усилий для написания кода и стоит только в том случае, если вы беспокоитесь о производительности.

Изменить: нашел еще лучший вариант без нескольких SELECTS:

DECLARE
   cols VARCHAR2(1000);
   null_count NUMBER;
BEGIN
   FOR aCol IN (SELECT COLUMN_NAME FROM USER_TAB_COLS WHERE TABLE_NAME = 'SOME_TABLE') LOOP
        cols := cols||'NVL2('||aCol.column_name||',0,1)+';
   END LOOP;
    EXECUTE IMMEDIATE 'SELECT SUM('||REGEXP_REPLACE(cols, '\+$')||') FROM SOME_TABLE WHERE condition = true' INTO null_count;
    DBMS_OUTPUT.PUT_LINE ( 'null_count = ' || null_count );
END;
person Wernfried Domscheit    schedule 01.12.2013