Se vuoi che questo venga fatto esclusivamente da MYSQL e senza enumerare tutte le colonne dai un'occhiata a questa soluzione.
In questo metodo non è necessario mantenere il numero di colonne del database codificandole in modo rigido. Se lo schema della tua tabella verrà modificato, questo metodo funzionerà e non richiederà la modifica del codice.
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 viene utilizzato per evitare la lettura, concatenando colonne molto lunghe per niente, inoltre l'ASCII ci rende sicuri per i valori in cui il primo carattere è una virgola(,).
Dal momento che stai lavorando con i rapporti, potresti trovarlo utile in quanto può essere riutilizzato per ogni tabella se inserisci un metodo.
Ho cercato di lasciare più commenti possibili.
Dividiamo in pezzi nel modo compatto sopra (modo inverso):
Volevo finire per avere una domanda come questa
SELECT totalcolumns - notnullcolumns from table; -- to return null columns for each row
Mentre il primo è facile da calcolare eseguendo:
SELECT count(*) FROM information_schema.columns where [email protected] and [email protected];
La seconda, le notnullcolumns, è un po' dolorosa. Dopo un esame delle funzioni disponibili in MySQL, rileviamo che CONCAT_WS non CONCAT valori nulli
Quindi eseguire una query come questa:
SELECT CONCAT_WS(",","First name",NULL,"Last Name");
returns: 'First name,Last Name'
Questo è positivo, ci sbarazziamo dei valori nulli dall'enumerazione. Ma come otteniamo quante colonne sono state effettivamente concatenate?
Bene, è difficile. Dobbiamo calcolare il numero di virgole+1 per ottenere le colonne effettivamente concatenate.
Per questo trucco abbiamo utilizzato la seguente notazione SQL
select length(value)-length(replace(value,',','')) +1 from table
Ok, quindi ora abbiamo il numero di colonne concatenate.
Ma la parte più difficile verrà dopo.
Dobbiamo enumerare per CONCAT_WS() tutti i valori.
Dobbiamo avere qualcosa del genere:
SELECT CONCAT_WS(",",col1,col2,col3,col4,col5);
È qui che dobbiamo utilizzare le istruzioni preparate, poiché dobbiamo preparare una query SQL in modo dinamico da colonne ancora sconosciute. Non sappiamo quante colonne ci saranno nella nostra tabella.
Quindi per questo utilizziamo i dati della tabella delle colonne information_schema. Dobbiamo passare il nome della tabella, ma anche il nome del database, poiché potremmo avere lo stesso nome della tabella in database separati.
Abbiamo bisogno di una query che ci restituisca col1, col2, col3, col4, col5 sulla "stringa" CONCAT_WS
Quindi per questo eseguiamo una query
SELECT group_concat(column_name SEPARATOR ",") into @x from information_schema.columns where [email protected] and [email protected];
Un'altra cosa da menzionare. Quando abbiamo usato il metodo length() e replace() per scoprire quante colonne sono state concatenate, dobbiamo assicurarci di non avere virgole tra i valori. Ma prendi anche nota che possiamo avere valori molto lunghi nelle nostre celle di database. Per entrambi questi trucchi utilizziamo il metodo ASCII('value'), che restituirà il carattere ASCII del primo carattere, che non può essere una virgola e restituirà null per le colonne nulle.
Detto questo, possiamo compattare tutto questo nella soluzione completa di cui sopra.