すべての列を列挙せずにMYSQLだけでこれを実行したい場合は、このソリューションを見てください。
この方法では、データベースの列をハードコーディングして維持する必要はありません。テーブルスキーマが変更される場合、このメソッドは機能し、コードを変更する必要はありません。
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は、読み取りを回避するために使用され、非常に長い列を無料で連結します。また、ASCIIを使用すると、最初の文字がコンマ(、)である値に対して安全になります。
レポートを操作しているので、メソッドを入力するとテーブルごとに再利用できるため、これが役立つ場合があります。
できるだけ多くのコメントをさせてみました。
上記のコンパクトな方法(逆の方法)で分割してみましょう:
このようなクエリを作成したかったのです
SELECT totalcolumns - notnullcolumns from table; -- to return null columns for each row
最初のものは実行することで簡単に計算できますが:
SELECT count(*) FROM information_schema.columns where [email protected] and [email protected];
2番目のnotnullcolumnsは少し面倒です。MySQLで使用可能な関数を調べた後、CONCAT_WSがnull値をCONCATしないことを検出しました
したがって、次のようなクエリを実行します:
SELECT CONCAT_WS(",","First name",NULL,"Last Name");
returns: 'First name,Last Name'
これは良いことです。列挙からnull値を取り除きますが、実際に連結された列の数を取得するにはどうすればよいでしょうか。
それはトリッキーです。実際に連結された列を取得するには、コンマの数+1を計算する必要があります。
このトリックでは、次のSQL表記を使用しました
select length(value)-length(replace(value,',','')) +1 from table
これで、連結された列の数がわかりました。
しかし、次に難しい部分があります。
CONCAT_WS()のすべての値を列挙する必要があります。
次のようなものが必要です:
SELECT CONCAT_WS(",",col1,col2,col3,col4,col5);
これは、まだ不明な列から動的にSQLクエリを準備する必要があるため、準備されたステートメントを使用する必要がある場所です。テーブルにいくつの列があるかわかりません。
したがって、このために、information_schema列テーブルのデータを使用します。別のデータベースに同じテーブル名がある可能性があるため、テーブル名だけでなくデータベース名も渡す必要があります。
CONCAT_WS「文字列」でcol1、col2、col3、col4、col5を返すクエリが必要です
したがって、このためにクエリを実行します
SELECT group_concat(column_name SEPARATOR ",") into @x from information_schema.columns where [email protected] and [email protected];
もう1つ言及します。 length()メソッドとreplace()メソッドを使用して、連結された列の数を調べる場合、値の間にコンマが含まれていないことを確認する必要があります。ただし、データベースセルに非常に長い値を含めることができることにも注意してください。このトリックの両方で、メソッドASCII('value')を使用します。これは、最初の文字のASCII文字を返します。これはコンマにすることはできず、null列の場合はnullを返します。
そうは言っても、上記の包括的なソリューションでこれらすべてを圧縮することができます。