2010-08-13 4 views
0

У меня очень сложный запрос в PostgreSQL, который объединяет несколько таблиц, все из которых имеют общий набор полей, которые мы хотим объединить. в настоящее время мы предвосхищаем этот запрос. Я видел решение этого с помощью UNPIVOT, и мне интересно, можно ли это сделать в PostgreSQL-аромате 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. Изменение схемы не является вариантом.

+2

Похоже, плохой дизайн базы данных. :(Удачи! –

+0

Ну, я упростил, от него многое зависит, и есть только небольшой набор перекрывающихся столбцов, которые мне нужны в объединении для сбора статистики. – Marcin

ответ

3

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

Схема будет выглядеть следующим образом:

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

С помощью этой конструкции, вы можете сделать простой выбор:

SELECT * FROM base; 

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

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

+0

+1 Разделение отлично. Можно также удалять и обновления, просто работая с родительской таблицей. – mikelikespie

2

Если вы действительно не можете исправить свой дизайн (или не хотите использовать очень хорошее предложение от 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_source, а затем выполняет объединение и возвращает результат.

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

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

 
select * 
from my_union() 
Смежные вопросы