2010-02-19 3 views
4

Просто интересно, есть ли быстрый способ подсчитать все значения NULL (из всех столбцов) в таблице MySQL?Как подсчитать все значения NULL в таблице?

Спасибо за любую идею!

+0

Существует способ, которым вы можете достичь в MySQL исключительно с помощью SQL. Код не прост. Взгляните на решение, отправленное мной. – Pentium10

ответ

4

Если вы хотите, чтобы это сделано исключительно MYSQL и без перечисления всех столбцов взять Посмотрите на это решение.

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

SET @db = 'testing'; -- database 
SET @tb = 'fuzzysearch'; -- table 
SET @x = ''; -- will hold the column names with ASCII method applied to retrieve the number of the first char 
SET @numcolumns = 0; -- will hold the number of columns in the table 

-- figure out how many columns we have 
SELECT count(*) into @numcolumns FROM information_schema.columns where [email protected] and [email protected]; 

-- we have to prepare some query from all columns of the table 
SELECT group_concat(CONCAT('ASCII(',column_name,')') SEPARATOR ",") into @x from information_schema.columns where [email protected] and [email protected]; 
-- after this query we have a variable separated with comma like 
-- ASCII(col1),ASCII(col2),ASCII(col3) 

-- we now generate a query to concat the columns using comma as separator (null values are omitted from concat) 
-- then figgure out how many times the comma is in that substring (this is done by using length(value)-length(replace(value,',','')) 
-- the number returned is how many non null columns we have in that column 
-- then we deduct the number from the known number of columns, calculated previously 
-- the +1 is added because there is no comma for single value 
SET @s = CONCAT('SELECT @numcolumns - (length(CONCAT_WS(\',\',', @x, '))-length(replace(CONCAT_WS(\',\',', @x, '),\',\',\'\')) + 1) FROM ',@db,'.',@tb,';'); 
PREPARE stmt FROM @s; 
EXECUTE stmt; 
-- after this execution we have returned for each row the number of null columns 
-- I will leave to you to add a sum() group call if you want to find the null values for the whole table 
DEALLOCATE PREPARE stmt; 

ASCII-используется, чтобы избежать чтения, конкатенации очень длинные столбцы ничего, и ASCII делает нас безопасным для значений, где первый символ запятой (,).

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

Я попытался дать как можно больше комментариев.

разобьет на кусках выше компактный способ (обратный путь):

Я хотел в конечном итоге, запрос, как этот

SELECT totalcolumns - notnullcolumns from table; -- to return null columns for each row 

В то время как первый один легко calcule команды:

SELECT count(*) FROM information_schema.columns where [email protected] and [email protected]; 

Во-вторых, notnullcolumns немного больно. После куска рассмотрения функций, доступных в MySQL, мы обнаружим, что CONCAT_WS не Concat нулевых значений

Так работает запрос, как это:

SELECT CONCAT_WS(",","First name",NULL,"Last Name"); 
returns: 'First name,Last Name' 

Это хорошо, мы принимаем избавиться от нулевого значения из перечисления. Но как мы можем получить, сколько столбцов было фактически конкатенировано?

Ну, это сложно.Нам нужно вычислить число запятых + 1, чтобы получить фактически конкатенированные столбцы.

Для этого трюка мы использовали следующий SQL нотацию

select length(value)-length(replace(value,',','')) +1 from table 

Итак, мы имеем теперь число каскадных столбцов.

Но более сложная часть будет следующей.

Мы должны перечислять для CONCAT_WS() все значения.
Нам нужно иметь что-то вроде этого:

SELECT CONCAT_WS(",",col1,col2,col3,col4,col5); 

Здесь мы должны принять использование подготовленных заявлений, так как мы должны подготовить запрос SQL динамически еще неизвестных столбцов. Мы не знаем, сколько столбцов будет в нашей таблице.

Для этого мы используем данные из таблицы столбцов information_schema. Нам нужно передать имя таблицы, но также имя базы данных, так как мы можем иметь одно и то же имя таблицы в отдельных базах данных.

Нам нужен запрос, который возвращает col1, col2, col3, COL4, col5 к нам на CONCAT_WS "строка"

Так что для этого запустить запрос

SELECT group_concat(column_name SEPARATOR ",") into @x from information_schema.columns where [email protected] and [email protected]; 

еще одна вещь, чтобы упомянуть , Когда мы использовали метод length() и replace(), чтобы узнать, сколько столбцов было объединено, мы должны убедиться, что у нас нет запятых среди значений. Но также обратите внимание, что мы можем иметь очень длинные ценности в наших ячейках базы данных. Для обоих этих трюков мы используем метод ASCII ('value'), который возвращает символ ASCII первого символа, который не может быть запятой и возвращает значение null для нулевых столбцов.

При этом мы можем скомпоновать все это в вышеупомянутом комплексном решении.

+0

+1, хотя это немного сложно понять и поддерживать – Bozho

+0

. Я добавил больше комментариев, и этот метод не нуждается в обслуживании, если он изменяет схему таблицы, он будет работать без изменения кода. Таким образом, его можно использовать повторно по другим причинам. – Pentium10

+0

Это было очень долго и замечательно, и я решил проблему. Любое число при выполнении этой функции? Благодаря! – Nirmal

4

Что-то вроде

select id 
     , sum (case when col1 is null then 1 else 0 end case) col1 
     , sum (case when col2 is null then 1 else 0 end case) col2 
     , sum (case when col3 is null then 1 else 0 end case) col3 
from contacts 
group by id 
+0

Это связано с пониманием количества столбцов для этой таблицы, на большой таблице это неэффективно. Проверьте мое решение. – Pentium10

+0

@Pentium - вы говорите правду, есть способы обойти это. Для одноразового запроса достаточно простого регулярного выражения против вырезанного вывода DESCRIBE. Или запрос может быть создан из INFORMATION_SCHEMA. – APC

0

Вы действительно должны сделать это, используя не только SQL, но язык, который находится в вашем распоряжении:

  1. Получить метаданные каждой таблицы - либо с помощью DESCRIBE table, или используя встроенные функции метаданных в вашей технологии доступа к db

  2. Создайте запросы следующего типа в цикле для каждого столбца п. (В псевдокоде)

    int nulls = 0; 
    for (String colmnName : columNames) { 
        query = "SELECT COUNT(*) FROM tableName WHERE " + columnName + " IS NULL"; 
        Result result = executeQuery(query); 
        nulls += result.size(); 
    } 
    
+0

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

+0

мне кажется, что он делает единовременную статистику, поэтому он может позволить ему работать в течение целого дня, если необходимо :) – Bozho

0

Что-то вроде этого (заменить COL_COUNT в зависимости от обстоятельств):

select count(*) * COL_COUNT - count(col1) - count(col2) - ... - count(col_n) from table; 
+0

Это связано с пониманием количества столбцов для этой таблицы, на большой таблице это неэффективно. Проверьте мое решение. – Pentium10

Смежные вопросы