Als je wilt dat dit exclusief door MYSQL wordt gedaan en zonder alle kolommen op te sommen, kijk dan eens naar deze oplossing.
Bij deze methode hoeft u het aantal databasekolommen niet bij te houden door ze hard te coderen. Als uw tabelschema wordt gewijzigd, werkt deze methode en hoeft u geen code te wijzigen.
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;
De ASCII wordt gebruikt om lezen te voorkomen, waarbij zeer lange kolommen voor niets worden samengevoegd, en ASCII maakt ons ook veilig voor waarden waarbij het eerste teken een komma(,) is.
Aangezien u met rapporten werkt, kan dit nuttig zijn, omdat deze voor elke tabel opnieuw kan worden gebruikt als u een methode invoert.
Ik heb geprobeerd zoveel mogelijk opmerkingen te plaatsen.
Laten we de bovenstaande compacte manier in stukken splitsen (omgekeerde manier):
Ik wilde uiteindelijk een vraag als deze hebben
SELECT totalcolumns - notnullcolumns from table; -- to return null columns for each row
Terwijl de eerste gemakkelijk te berekenen is door uit te voeren:
SELECT count(*) FROM information_schema.columns where [email protected] and [email protected];
De tweede, de niet-nullkolommen, is een beetje pijnlijk. Na een stukje onderzoek van de functies die beschikbaar zijn in MySQL, ontdekken we dat CONCAT_WS geen CONCAT-nulwaarden bevat
Dus voer een zoekopdracht als volgt uit:
SELECT CONCAT_WS(",","First name",NULL,"Last Name");
returns: 'First name,Last Name'
Dit is goed, we verwijderen de null-waarden uit de opsomming. Maar hoe komen we erachter hoeveel kolommen daadwerkelijk aaneengeschakeld zijn?
Nou, dat is lastig. We moeten het aantal komma's+1 berekenen om de daadwerkelijk aaneengeschakelde kolommen te krijgen.
Voor deze truc hebben we de volgende SQL-notatie gebruikt
select length(value)-length(replace(value,',','')) +1 from table
Ok, dus we hebben nu het aantal aaneengeschakelde kolommen.
Maar het moeilijkere deel komt hierna.
We moeten voor CONCAT_WS() alle waarden opsommen.
We hebben zoiets als dit nodig:
SELECT CONCAT_WS(",",col1,col2,col3,col4,col5);
Dit is waar we gebruik moeten maken van de voorbereide instructies, omdat we een SQL-query dynamisch moeten voorbereiden vanuit nog onbekende kolommen. We weten niet hoeveel kolommen er in onze tabel zullen staan.
Dus hiervoor gebruiken we gegevens uit de informatie_schema-kolommentabel. We moeten de tabelnaam doorgeven, maar ook de databasenaam, aangezien we dezelfde tabelnaam in afzonderlijke databases kunnen hebben.
We hebben een query nodig die col1,col2,col3,col4,col5 naar ons terugstuurt op de CONCAT_WS "string"
Dus hiervoor voeren we een query uit
SELECT group_concat(column_name SEPARATOR ",") into @x from information_schema.columns where [email protected] and [email protected];
Nog een ding om te vermelden. Toen we de methode length() en Replace() gebruikten om erachter te komen hoeveel kolommen aaneengeschakeld waren, moesten we ervoor zorgen dat er geen komma's tussen de waarden staan. Maar houd er ook rekening mee dat we echt lange waarden in onze databasecellen kunnen hebben. Voor beide trucs gebruiken we methode ASCII('value'), die het ASCII-teken van het eerste teken teruggeeft, dat geen komma mag zijn en null teruggeeft voor null-kolommen.
Dat gezegd hebbende, kunnen we dit alles comprimeren in de bovenstaande allesomvattende oplossing.