Упростите сложное объединение всех в PostgreSQL

У меня есть очень сложный запрос в PostgreSQL, который объединяет несколько таблиц, и все они имеют общий набор полей, которые мы хотим объединить. в настоящее время мы предварительно генерируем этот запрос. Я видел решение этой проблемы с помощью UNPIVOT, и мне интересно, возможно ли это сделать в версии SQL PostgreSQL.

У меня что-то вроде

SELECT a,b,c FROM a UNION ALL
SELECT a,b,c FROM c UNION ALL
SELECT a,b,c FROM d UNION ALL
SELECT a,b,c FROM e UNION ALL
SELECT a,b,c FROM f

Я хотел бы, чтобы имена таблиц объединялись в отдельную таблицу и использовали ее для этого запроса.

PS. Менять схему не вариант.


person Marcin    schedule 13.08.2010    source источник
comment
Звучит как плохой дизайн базы данных. :( Удачи!   -  person Mark Byers    schedule 14.08.2010
comment
Ну, я упростил, от этого зависит многое, и есть только небольшой набор перекрывающихся столбцов, которые мне нужны в объединении для сбора статистики.   -  person Marcin    schedule 15.08.2010


Ответы (2)


Используйте наследование для документации Postgres для наследования. Вам нужно будет воссоздать базу данных, но это легко сделать, если вы выгрузите таблицы без схемы, создадите новую схему с наследованием и загрузите данные обратно.

Схема будет выглядеть примерно так:

CREATE TABLE base (a, b, c);
CREATE TABLE a () INHERITS (base);
CREATE TABLE b () INHERITS (base);
....

С этим дизайном вы можете сделать простой выбор:

SELECT * FROM base;

Это вернет все строки в base и все таблицы, унаследованные от base.

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

person jmz    schedule 14.08.2010
comment
+1 разбиение отличное. Можно также выполнять удаления и обновления, просто работая с родительской таблицей. - person mikelikespie; 18.08.2010

Если вы действительно не можете исправить свой дизайн (или не хотите использовать очень хорошее предложение от jmz), ваш единственный выбор, вероятно, — функция, возвращающая набор, которая создает необходимый UNION «на лету», а затем возвращает результаты из тот.

create or replace function my_union()
 returns table(a integer, b integer, c integer)
as
$body$
declare
  union_cursor refcursor;
  table_cursor cursor for SELECT table_name FROM union_source; 
  union_query text := '';
begin

  -- build the query string for the union
  for table_list_record in table_cursor loop
    if union_query  '' then 
      union_query := union_query||' UNION ALL';
    end if;
    union_query := union_query||' SELECT a,b,c FROM '||table_list_record.table_name;
  end loop;

  -- run the union and return the result
  for a,b,c IN EXECUTE union_query LOOP
    return next;
  end loop; 
end;
$body$
language plpgsql;

Функция создает необходимый UNION на основе имен таблиц в union_source, затем выполняет объединение и возвращает результат.

Вы можете расширить таблицу union_source, чтобы также хранить список столбцов для каждой таблицы, если столбцы не всегда имеют одинаковые имена.

Чтобы использовать эту функцию, просто выберите из нее:

select *
from my_union()
person a_horse_with_no_name    schedule 15.08.2010