我需要选择所有存在至少一个值的同语。例如,如果这是我的桌子:
----------------------------
name | keyword | zip
----------------------------
User1 | test | ""
User2 | test | ""
User3 | "" | ""
应输出如下内容:
-----------------
name | keyword
-----------------
User1 | test
User2 | test
User3 | ""
问题是zip可能不会为空,在这种情况下,输出还应该包含zip列。我需要此功能的实际表具有许多可能为空的列。
我尝试使用SELECT * FROM myTable HAVING COUNT(*) > 0
,但是没有用(仍然显示空列)。
也尝试使用php使用循环来解决它,但也没有达到目标。
是否可以使用SQL这样的事情?例如是否应该使用php完成?
这是我使用针对该问题的建议在PHP中想到的解决方案。
$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."'";
这将输出以下sql查询:
SELECT name, keyword FROM myTable WHERE id = 'postedId'
请注意,选择中缺少zip
,这是因为对于该特定查询,zip中没有值。在$stack
数组中,您可以放置任何要检查的列。
还要记下我是如何使用!= ''
检查空值的,但是如果表中的空值为NULL
,请确保使用IS NOT NULL
。
答案 0 :(得分:1)
这是很痛苦的事情,并不是真正的SQL精神-在select
语句编写语句时,它定义了固定数量的列。
也就是说,您可以使用两个级别的动态SQL,一个级别获取列,而另一个级别使用列:
-- 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;
注意:在实际的应用程序中,您需要取消分配准备好的语句。
Here是db <>小提琴,用于说明此过程。
答案 1 :(得分:1)
这不是真正的答案。
只是一个有关如何在Oracle中完成操作的示例(我对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;