I need to select all coulmns where at least one value is present. For example if this is my table:
----------------------------
name | keyword | zip
----------------------------
User1 | test | ""
User2 | test | ""
User3 | "" | ""
Should output something like this:
-----------------
name | keyword
-----------------
User1 | test
User2 | test
User3 | ""
The thing is that zip might not be empty and in this case the output should also include the zip column. The actual table I need this functionality for has many more columns that can potentially be empty.
I tried using SELECT * FROM myTable HAVING COUNT(*) > 0
but that did not work (empty columns were still showing).
Also tried solving it with php using loops but didn't get far that way either.
Is something like this even possible using SQL or should it be done using php for example?
Here's the solution I came up with in PHP using the suggestions I got for this question.
$stack = array("keyword", "zip");
$id = $_POST["id"];
$sql = "SELECT name";
foreach($stack as $i){
$q = "SELECT ".$i." FROM myTable WHERE ".$i." != '' AND id = '".$id."'";
$result = mysqli_query($link, $q);
if(mysqli_num_rows($result) > 0){
$sql = $sql.", ".$i;
}
}
$sql = $sql." FROM myTable WHERE id = '".$id."'";
This will output the following sql query: SELECT name, keyword FROM myTable WHERE id = 'postedId'
Notice the zip
is missing from select, this is because for that particular query there were no values in zip. In the $stack
array you can put whatever columns you want to check.
Also make note of how I used != ''
to check for empty values but if your table has empty values as NULL
make sure to use IS NOT NULL
instead.
This is quite painful and not really in the spirit of SQL -- where a select
statement has a fixed number of columns defined when the statement is written.
That said, you can use two levels of dynamic SQL, one to get the columns and one to use them:
-- generate the SQL to identify the columns
select @sql := group_concat(replace('select max(''[column_name]'') as col from t having count([column_name]) > 0', '[column_name]', c.column_name)
separator ' union all ' )
from information_schema.columns c
where table_name = 't';
-- use the SQL to get the columns
select @sql := concat('select group_concat(col separator '', '') into @cols from (', @sql, ') x');
-- run the SQL
prepare s from @sql;
execute s ;
-- create the final query using the columns
set @sql2 = concat('select ', @cols, ' from t');
-- and execute it
prepare s2 from @sql2;
execute s2;
Note: in a real application, you would want to deallocate the prepared statements.
Here is a db<>fiddle illustrating this process.
This is not a the real answer.
Just an example of how it could be done in Oracle (I got very little experience with MySQL):
DECLARE
has_keyword INTEGER;
has_zip INTEGER;
sql VARCHAR2(1024);
BEGIN
-- Determine the columns having at least 1 row with a not null value
SELECT CASE WHEN MAX(keyword) IS NULL THEN 0 ELSE 1 END,
CASE WHEN MAX(zip) IS NULL THEN 0 ELSE 1 END
INTO has_keyword,
has_zip
FROM my_table;
-- Compose query
sql := 'SELECT name';
IF (has_keyword > 0) THEN
sql := sql || ', keyword';
END IF;
IF (zip > 0) THEN
sql := sql || ', zip';
END IF;
sql := sql || ' FROM my_table';
-- Execute query
EXECUTE IMMEDIATE sql;
END;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.