Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como contar todos os valores NULL em uma tabela?


Se você deseja que isso seja feito exclusivamente pelo MYSQL e sem enumerar todas as colunas, dê uma olhada nesta solução.

Neste método, você não precisa manter o número de colunas do banco de dados codificando-as. Se seu esquema de tabela for modificado, este método funcionará e não exigirá alteração de código.
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;

O ASCII é usado para evitar a leitura, concatenando colunas muito longas para nada, também o ASCII nos torna seguros para valores onde o primeiro caractere é uma vírgula (,).

Como você está trabalhando com relatórios, isso pode ser útil, pois isso pode ser reutilizado para cada tabela se você inserir um método.

Tentei deixar o máximo de comentários possível.

Vamos dividir em pedaços da forma compacta acima (maneira inversa):

Eu queria acabar tendo uma consulta como esta
SELECT totalcolumns - notnullcolumns from table; -- to return null columns for each row

Enquanto o primeiro é fácil de calcular executando:
SELECT count(*) FROM information_schema.columns where [email protected] and [email protected];

A segunda, as colunas não nulas, é um pouco trabalhosa. Após um exame das funções disponíveis no MySQL, detectamos que CONCAT_WS não contém valores nulos de CONCAT

Então, executando uma consulta como esta:
SELECT CONCAT_WS(",","First name",NULL,"Last Name");
returns: 'First name,Last Name'

Isso é bom, nos livramos dos valores nulos da enumeração. Mas como obtemos quantas colunas foram realmente concatenadas?

Bem, isso é complicado. Temos que calcular o número de vírgulas + 1 para obter as colunas realmente concatenadas.

Para este truque usamos a seguinte notação SQL
select length(value)-length(replace(value,',','')) +1 from table

Ok, agora temos o número de colunas concatenadas.

Mas a parte mais difícil vem a seguir.

Temos que enumerar para CONCAT_WS() todos os valores.
Precisamos ter algo assim:
SELECT CONCAT_WS(",",col1,col2,col3,col4,col5);

É aqui que temos que usar as instruções preparadas, pois temos que preparar uma consulta SQL dinamicamente a partir de colunas ainda desconhecidas. Não sabemos quantas colunas estarão em nossa tabela.

Então, para isso, usamos dados da tabela de colunas information_schema. Precisamos passar o nome da tabela, mas também o nome do banco de dados, pois podemos ter o mesmo nome de tabela em bancos de dados separados.

Precisamos de uma consulta que retorne col1,col2,col3,col4,col5 para nós na "string" CONCAT_WS

Então, para isso, executamos uma consulta
SELECT group_concat(column_name SEPARATOR ",") into @x from information_schema.columns where [email protected] and [email protected];

Mais uma coisa a mencionar. Quando usamos o método length() e replace() para descobrir quantas colunas foram concatenadas, temos que nos certificar de que não temos vírgulas entre os valores. Mas também observe que podemos ter valores muito longos em nossas células de banco de dados. Para ambos os truques, usamos o método ASCII('value'), que retornará o caractere ASCII do primeiro caractere, que não pode ser vírgula e retornará nulo para colunas nulas.

Dito isto, podemos compactar tudo isso na solução abrangente acima.