Как использовать pl / pgSQL для обработки возвратов из списка через запятую? - PullRequest
0 голосов
/ 09 января 2019

Я пытаюсь UNION ALL много таблиц в новую таблицу. Столбцы старых таблиц одинаковы, но порядок столбцов отличается, поэтому приведенный ниже оператор SQL получит неправильный результат:

CREATE TABLE sum_7_2018_xia_weijian
AS
(
        SELECT * FROM huiwen
        UNION
        SELECT * FROM penglai
        UNION
        SELECT * FROM baoluo
        UNION
        SELECT * FROM dongge
        UNION
        SELECT * FROM resultdonglu
        UNION
        SELECT * FROM resultwencheng
        UNION
        SELECT * FROM tan_illeg
);

Я наконец исправил это, но операторы SQL слишком избыточны:

шаг 1. получить имена столбцов одной из старых таблиц с именем huiwen

SELECT string_agg(column_name, ',')
                FROM information_schema.columns
                WHERE table_schema = 'public' AND table_name   = 'huiwen';

Результаты:

>                                      string_agg                                     
> ----------------------------------------------------------------------
>
>  gid,id,geom,sxm,sxdm,sxxzqdm,xzqhdm,xzmc,sfzgjsyd,sfkfbj,sfjbnt,sfld,sflyhx,sfhyhx

шаг 2. объединение таблиц в новую таблицу. Я копирую string_agg таблицы huiwen в каждый SELECT-UNION, чтобы сохранить порядок столбцов, это неуклюже.

CREATE TABLE sum_2018_xia_weijian
AS
(
        SELECT gid,id,geom,sxm,sxdm,sxxzqdm,xzqhdm,xzmc,sfzgjsyd,sfkfbj,sfjbnt,sfld,sflyhx,sfhyhx
        FROM huiwen
        UNION ALL
        SELECT gid,id,geom,sxm,sxdm,sxxzqdm,xzqhdm,xzmc,sfzgjsyd,sfkfbj,sfjbnt,sfld,sflyhx,sfhyhx
        FROM penglai
        UNION ALL
        SELECT gid,id,geom,sxm,sxdm,sxxzqdm,xzqhdm,xzmc,sfzgjsyd,sfkfbj,sfjbnt,sfld,sflyhx,sfhyhx
        FROM baoluo
);

Результаты:

> Query returned successfully: 2206 rows affected, 133 msec execution time.

Я попытался провести некоторую оптимизацию с помощью pl/pgSQL, используя Declarations переменной для обработки имен столбцов, но не смог найти какой-либо тип данных SQL, который мог бы справиться с этим. Использование RECORD результат Pseudo-Types ERROR

CREATE or replace FUNCTION ct() RETURNS RECORD AS $$
DECLARE
    clms RECORD;
BEGIN
    SELECT column_name INTO clms
        FROM information_schema.columns
        WHERE table_schema = 'public' AND table_name = 'huiwen';
    RETURN clms;
END;
$$ LANGUAGE plpgsql;
CREATE TABLE sum_2018_xia_weijian
AS
(
    SELECT ct() FROM huiwen
    UNION ALL
    SELECT ct() FROM penglai
    UNION ALL
    SELECT ct() FROM baoluo
    UNION ALL
    SELECT ct() FROM dongge
    UNION ALL
    SELECT ct() FROM resultdonglu
    UNION ALL
    SELECT ct() FROM resultwencheng
    UNION ALL
    SELECT ct() FROM tan_illeg
);

Ответы [ 2 ]

0 голосов
/ 09 января 2019

Вы можете использовать STRING_AGG дважды для получения UNION ALL. Вы можете получить все столбцы в определенном порядке, явно упорядочив их по column_name в string_agg.

Вот обобщенная функция, которая принимает массив таблиц и окончательное имя таблицы.

CREATE or replace FUNCTION fn_create_tab(tname_arr TEXT[], p_tab_name TEXT) 
RETURNS VOID AS $$
DECLARE
l_select TEXT;
BEGIN
   select STRING_AGG(query,' UNION ALL ' ) INTO l_select
    FROM
    (
     SELECT 'select ' || string_agg( column_name,','
     ORDER BY column_name ) || ' from ' || table_name as query
       FROM information_schema.columns
      WHERE table_schema = 'public' AND table_name = ANY (tname_arr)
     GROUP BY table_name
     ) s;

 IF l_select IS NOT NULL
  THEN
    EXECUTE format ('DROP TABLE IF EXISTS %I',p_tab_name);
    EXECUTE format ('create table %I  AS %s',p_tab_name,l_select);
  END IF;    
END;
$$ LANGUAGE plpgsql;

Теперь запустите функцию следующим образом:

select fn_create_tab(ARRAY['huiwen','penglai'],'sum_2018_xia_weijian');
0 голосов
/ 09 января 2019

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

  1. Количество столбцов во всех запросах должно быть одинаковым.
  2. Соответствующие столбцы должны иметь совместимый тип данных.
  3. Имена столбцов первого запроса определяют имена столбцов объединенного набора результатов.
  4. Предложения GROUP BY и HAVING применяются к каждому отдельному запросу, а не к окончательному набору результатов.
  5. Предложение ORDER BY применяется к комбинированному набору результатов, а не к отдельному набору результатов.

Следуя 3-му пункту, настройте ваш запрос на объединение так, чтобы он ссылался на таблицу, порядок столбцов которой ожидается в результате.

...