SQL返回包含非NULL数据的字段列表

时间:2011-10-17 08:47:40

标签: mysql sql sqlite postgresql

如何从给定表中返回包含任何非NULL数据的字段列表?

作为示例,我如何查询下面的示例表,只返回以下三个值,因为它们包含除NULL之外的其他值。

  • LO2_HiddenOrgID
  • LO2_BranchOfOrgID
  • LO2_ShortName

Example Database

我希望尽可能自动化,因为我有几千个字段需要检查。

此外,我目前正在开发中使用SQLite,但很乐意接受任何特定于SQLite,MySQL或PostgreSQL的建议。

7 个答案:

答案 0 :(得分:2)

所以你的目标是获得列名列表,使得所有列中的任何一行都至少有一个非NULL值,对吧?如果是这样,请参见下文......

您无法在SQL查询中参数化列的名称,因此您需要使用您选择的客户端语言动态构建SQL文本。该算法如下所示:

  1. 您必须事先知道列名列表。有一些方法可以在PostgreSQLMySQL和大多数其他数据库中自动检索此列表。
  2. 遍历此列表,并为每个column_name动态构建SQL文本,例如:SELECT column_name FROM YOUR_TABLE WHERE column_name IS NOT NULL LIMIT 1(请参阅MySQL LIMIT和PostgreSQL LIMIT)。
  3. 执行上面的查询并获取结果。如果其中有一行,请将column_name添加到结果列表
  4. 在列名列表中有元素时继续迭代。
  5. 结果列表现在包含至少有一个非NULL值的列。

答案 1 :(得分:2)

PostgreSQL的全自动完整解决方案

返回所有模式中的所有(非系统)表,其中所有列至少具有一个非空值。
您必须是超级用户(如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'