Wenn Sie möchten, dass dies ausschließlich von MYSQL erledigt wird und ohne alle Spalten aufzuzählen, schauen Sie sich diese Lösung an.
Bei dieser Methode müssen Sie die Anzahl der Datenbankspalten nicht fest codieren. Wenn Ihr Tabellenschema geändert wird, funktioniert diese Methode und erfordert keine Codeänderung.
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 wird verwendet, um das Lesen zu vermeiden und sehr lange Spalten umsonst zu verketten, auch ASCII macht uns sicher für Werte, bei denen das erste Zeichen ein Komma (,) ist.
Da Sie mit Berichten arbeiten, ist dies möglicherweise hilfreich, da es für jede Tabelle wiederverwendet werden kann, wenn Sie eine Methode einfügen.
Ich habe versucht, so viele Kommentare wie möglich zuzulassen.
Lassen Sie uns auf die obige kompakte Weise (umgekehrte Weise) in Stücke aufteilen:
Ich wollte am Ende eine Abfrage wie diese haben
SELECT totalcolumns - notnullcolumns from table; -- to return null columns for each row
Während der erste leicht zu berechnen ist, indem Sie Folgendes ausführen:
SELECT count(*) FROM information_schema.columns where [email protected] and [email protected];
Die zweite, die notnullcolumns, ist ein bisschen mühsam. Nach einer Untersuchung der in MySQL verfügbaren Funktionen stellen wir fest, dass CONCAT_WS keine Nullwerte CONCAT.
Führen Sie also eine Abfrage wie folgt aus:
SELECT CONCAT_WS(",","First name",NULL,"Last Name");
returns: 'First name,Last Name'
Das ist gut, wir entfernen die Nullwerte aus der Aufzählung. Aber wie erhalten wir, wie viele Spalten tatsächlich verkettet wurden?
Nun, das ist schwierig. Wir müssen die Anzahl der Kommas + 1 berechnen, um die tatsächlich verketteten Spalten zu erhalten.
Für diesen Trick haben wir die folgende SQL-Notation verwendet
select length(value)-length(replace(value,',','')) +1 from table
Ok, also haben wir jetzt die Anzahl der verketteten Spalten.
Aber der schwierigere Teil kommt als nächstes.
Wir müssen für CONCAT_WS() alle Werte aufzählen.
Wir brauchen so etwas:
SELECT CONCAT_WS(",",col1,col2,col3,col4,col5);
Hier müssen wir auf die Prepared Statements zurückgreifen, da wir eine SQL-Abfrage dynamisch aus noch unbekannten Spalten aufbereiten müssen. Wir wissen nicht, wie viele Spalten unsere Tabelle haben wird.
Dazu verwenden wir also Daten aus der Spalte-Tabelle information_schema. Wir müssen den Tabellennamen übergeben, aber auch den Datenbanknamen, da wir möglicherweise denselben Tabellennamen in verschiedenen Datenbanken haben.
Wir brauchen eine Abfrage, die uns col1,col2,col3,col4,col5 auf der CONCAT_WS "Zeichenfolge"
zurückgibtDazu führen wir also eine Abfrage durch
SELECT group_concat(column_name SEPARATOR ",") into @x from information_schema.columns where [email protected] and [email protected];
Noch etwas zu erwähnen. Wenn wir die Methoden length() und replace() verwendet haben, um herauszufinden, wie viele Spalten verkettet wurden, müssen wir sicherstellen, dass zwischen den Werten keine Kommas stehen. Beachten Sie aber auch, dass wir sehr lange Werte in unseren Datenbankzellen haben können. Für beide dieser Tricks verwenden wir die Methode ASCII('value'), die das ASCII-Zeichen des ersten Zeichens zurückgibt, das kein Komma sein darf und null für Nullspalten zurückgibt.
Davon abgesehen können wir all dies in der oben genannten umfassenden Lösung komprimieren.