如何从给定表中返回包含任何非NULL数据的字段列表?
作为示例,我如何查询下面的示例表,只返回以下三个值,因为它们包含除NULL之外的其他值。
我希望尽可能自动化,因为我有几千个字段需要检查。
此外,我目前正在开发中使用SQLite,但很乐意接受任何特定于SQLite,MySQL或PostgreSQL的建议。
答案 0 :(得分:2)
所以你的目标是获得列名列表,使得所有列中的任何一行都至少有一个非NULL值,对吧?如果是这样,请参见下文......
您无法在SQL查询中参数化列的名称,因此您需要使用您选择的客户端语言动态构建SQL文本。该算法如下所示:
column_name
动态构建SQL文本,例如:SELECT column_name FROM YOUR_TABLE WHERE column_name IS NOT NULL LIMIT 1
(请参阅MySQL LIMIT和PostgreSQL LIMIT)。column_name
添加到结果列表。结果列表现在包含至少有一个非NULL值的列。
答案 1 :(得分:2)
返回所有模式中的所有(非系统)表,其中所有列至少具有一个非空值。
您必须是超级用户(如postgres)才能调用此功能
或者,超级用户可以拥有该功能,并使用SECURITY DEFINER创建。
CREATE OR REPLACE FUNCTION f_tbl_with_nonull_cols()
RETURNS TABLE(tbl text, columns text) AS
$BODY$
DECLARE
rel_id oid; -- oid of table
sch text; -- schema name
cols1 text; -- columns defined NOT NULL
cols2 text; -- other columns
q text; -- for query string
has_row bool; -- table has rows?
BEGIN
FOR rel_id, sch, tbl IN
SELECT c.oid -- AS rel_id
,n.nspname -- as sch
,c.relname -- as tbl
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r'
AND n.nspname <> 'pg_catalog'
AND n.nspname <> 'information_schema'
AND n.nspname !~ '^pg_toast'
AND pg_catalog.pg_table_is_visible(c.oid)
ORDER BY 2,3
LOOP
EXECUTE 'SELECT EXISTS (SELECT 1 FROM '
|| quote_ident(sch) ||'.' || quote_ident(tbl) || ')'
INTO has_row;
IF has_row THEN
-- defined NOT NULL -> must have values.
SELECT INTO cols1
string_agg(a.attname,', ')
FROM pg_catalog.pg_attribute a
WHERE a.attrelid = rel_id
AND a.attnum > 0
AND NOT a.attisdropped
AND a.attnotnull;
SELECT INTO q
'array_to_string(ARRAY['
|| string_agg('CASE WHEN count(' || quote_ident(a.attname)
|| ') > 0 THEN '''|| a.attname || ''' ELSE NULL END', ', ')
|| '], '', '')'
FROM pg_catalog.pg_attribute a
WHERE a.attrelid = rel_id
AND a.attnum > 0
AND NOT a.attisdropped
AND NOT a.attnotnull;
IF q IS NOT NULL THEN
EXECUTE 'SELECT ' || q || '
FROM ' || quote_ident(sch) || '.' || quote_ident(tbl)
INTO cols2;
columns := COALESCE(cols1 || ', ', '') || cols2;
ELSE
columns := COALESCE(cols1, '');
END IF;
RETURN NEXT;
ELSE
-- no rows, so no columns with non-null values
END IF;
END LOOP;
呼叫:
SELECT * FROM f_tbl_with_nonull_cols();
tbl | columns
----------------+----------------------------------
table1 | id, col1, col7,
table2 | id, col4, col5, col8, col9, col10
table5 | some_id
...
答案 2 :(得分:0)
SELECT LO2_HiddenOrgID FROM MyTable WHERE LO2_HiddenOrgID IS NOT NULL
UNION ALL
SELECT LO2_BranchOfOrgID FROM MyTable WHERE LO2_BranchOfOrgID IS NOT NULL
等等
答案 3 :(得分:0)
@citricguy:我相信您需要包含非空数据的所有列,而无需在查询中专门选择任何列。如果不是这样,请纠正我。
答案 4 :(得分:0)
@xanatos说的是什么,但是在所选列名称周围加上引号..
SELECT distinct 'LO2_HiddenOrgID' FROM MyTable WHERE LO2_HiddenOrgID IS NOT NULL
UNION ALL
SELECT distinct 'LO2_BranchOfOrgID' FROM MyTable WHERE LO2_BranchOfOrgID IS NOT NULL
UNION ALL
SELECT distinct 'LO2_HiddenOtyID' FROM MyTable WHERE LO2_HiddenOtyID IS NOT NULL
UNION ALL
SELECT distinct 'LO2_ShortName' FROM MyTable WHERE LO2_ShortName IS NOT NULL
答案 5 :(得分:0)
这不能完全回答您的问题,但此查询将返回每列中非空项的数量。如果检查返回的值,则可以输出字段。
SELECT COUNT(Col1) AS Col1, COUNT(Col2) AS Col2, COUNT(Col3) AS
Col3 ,
等....
FROM table
WHERE table.Col1 IS NOT NULL OR table.Col2 IS NOT NULL OR table.Col3 IS NOT NULL
等。
答案 6 :(得分:0)
在SQLite中,我会选择这样的东西,你可以在功能更丰富的RDBMS中做一些聪明的事情:
SELECT 'LO2_HiddenOrgID'
FROM MyTable
WHERE LO2_HiddenOrgID IS NOT NULL
LIMIT 1
UNION
SELECT 'LO2_BranchOfOrgID'
FROM MyTable
WHERE LO2_BranchOfOrgID IS NOT NULL
LIMIT 1
UNION
SELECT 'LO2_HiddenOtyID'
FROM MyTable
WHERE LO2_HiddenOtyID IS NOT NULL
LIMIT 1
应该可以根据存储在SQLite数据字典中的元数据动态生成上述查询:
SELECT *
FROM sqlite_master
WHERE tbl_name = 'MyTable'
AND type = 'table'