Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment compter toutes les valeurs NULL dans une table ?

Si vous voulez que cela soit fait exclusivement par MYSQL et sans énumérer toutes les colonnes, jetez un œil à cette solution.

Dans cette méthode, vous n'avez pas à gérer le nombre de colonnes de la base de données en les codant en dur. Si votre schéma de table est modifié, cette méthode fonctionnera et ne nécessitera pas de changement de code.

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;

L'ASCII est utilisé pour éviter la lecture, en concaténant de très longues colonnes pour rien, aussi l'ASCII nous rend sûrs pour les valeurs où le premier caractère est une virgule (,).

Puisque vous travaillez avec des rapports, cela peut vous être utile car cela peut être réutilisé pour chaque table si vous mettez une méthode.

J'ai essayé de laisser autant de commentaires que possible.

Divisons en morceaux de la manière compacte ci-dessus (sens inverse):

Je voulais finir par avoir une requête comme celle-ci

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

Alors que le premier est facile à calculer en exécutant :

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

La seconde, les colonnes notnull, est un peu pénible. Après un examen des fonctions disponibles dans MySQL, nous détectons que CONCAT_WS ne CONCATE pas les valeurs nulles

Exécutez donc une requête comme celle-ci :

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

C'est bien, nous nous débarrassons des valeurs nulles de l'énumération. Mais comment obtenir combien de colonnes ont été réellement concaténées ?

Eh bien, c'est délicat. Nous devons calculer le nombre de virgules + 1 pour obtenir les colonnes réellement concaténées.

Pour cette astuce, nous avons utilisé la notation SQL suivante

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

Ok, nous avons donc maintenant le nombre de colonnes concaténées.

Mais le plus dur vient ensuite.

Nous devons énumérer pour CONCAT_WS() toutes les valeurs.
Nous devons avoir quelque chose comme ceci :

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

C'est là que nous devons utiliser les instructions préparées, car nous devons préparer dynamiquement une requête SQL à partir de colonnes encore inconnues. Nous ne savons pas combien de colonnes il y aura dans notre tableau.

Donc, pour cela, nous utilisons les données de la table des colonnes information_schema. Nous devons transmettre le nom de la table, mais également le nom de la base de données, car nous pourrions avoir le même nom de table dans des bases de données distinctes.

Nous avons besoin d'une requête qui nous renvoie col1, col2, col3, col4, col5 sur la "chaîne" CONCAT_WS

Donc, pour cela, nous exécutons une requête

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

Encore une chose à mentionner. Lorsque nous avons utilisé les méthodes length() et replace() pour savoir combien de colonnes ont été concaténées, nous devons nous assurer que nous n'avons pas de virgules parmi les valeurs. Mais notez également que nous pouvons avoir des valeurs très longues dans nos cellules de base de données. Pour ces deux astuces, nous utilisons la méthode ASCII('value'), qui renverra le caractère ASCII du premier caractère, qui ne peut pas être une virgule et renverra null pour les colonnes nulles.

Cela étant dit, nous pouvons compacter tout cela dans la solution complète ci-dessus.