SQL возвращает список полей, содержащих ненулевые данные - PullRequest
2 голосов
/ 17 октября 2011

Как я могу вернуть список полей из данной таблицы, которые содержат любые ненулевые данные?

В качестве примера, как я могу запросить приведенную ниже таблицу примеров, чтобы вернуть только следующие три значения, поскольку онисодержат что-то отличное от NULL.

  • LO2_HiddenOrgID
  • LO2_BranchOfOrgID
  • LO2_ShortName

Example Database

I 'Я стараюсь максимально автоматизировать это, так как у меня есть несколько тысяч полей для проверки.

Кроме того, в настоящее время я использую SQLite при разработке, но с удовольствием приму любые предложения, касающиеся SQLite, MySQL или PostgreSQL.

Ответы [ 7 ]

2 голосов
/ 17 октября 2011

Итак, ваша цель - получить список имен столбцов , чтобы у всех них было хотя бы одно ненулевое значение в любой из строк, верно? Если это так, см. Ниже ...

Вы не можете параметризовать имена столбцов в запросе SQL, поэтому вам нужно будет динамически создавать текст SQL на выбранном вами языке клиента. Алгоритм будет выглядеть так:

  1. Вам необходимо знать список имен столбцов заранее. Есть способы автоматизировать получение этого списка в PostgreSQL , MySQL и большинстве других баз данных.
  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. Продолжайте итерацию, пока в списке имен столбцов есть элементы.

Полученный список теперь содержит столбцы, по крайней мере, с одним ненулевым значением.

2 голосов
/ 17 октября 2011

Полностью автоматизированное, полное решение для PostgreSQL

Возвращает все (не системные) таблицы во всех схемах со всеми столбцами, которые имеют хотя бы одно ненулевое значение.
Вы должны быть суперпользователем (как postgres) для вызова этой функции.
Или вы, суперпользователь, можете владеть функцией, и она создается с помощью DEFINER SECURITY .

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
...
0 голосов
/ 17 октября 2011

В SQLite я бы пошел на что-то вроде этого, есть умные вещи, которые вы могли бы сделать в более многофункциональной СУБД:

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'
0 голосов
/ 17 октября 2011

Это не совсем отвечает на ваш вопрос, но этот запрос будет возвращать количество ненулевых элементов в каждом столбце.Если вы проверите проверенные значения, вы можете вывести поля.

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 и т. Д.

0 голосов
/ 17 октября 2011

Что сказал @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 
0 голосов
/ 17 октября 2011

@ citricguy: я считаю, что вам нужны все столбцы, которые содержат ненулевые данные, без особого выбора каких-либо столбцов в запросе. Поправь меня, если это не так.

0 голосов
/ 17 октября 2011
SELECT LO2_HiddenOrgID FROM MyTable WHERE LO2_HiddenOrgID IS NOT NULL 
UNION ALL
SELECT LO2_BranchOfOrgID FROM MyTable WHERE LO2_BranchOfOrgID IS NOT NULL 

и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...