2010-08-13 14 views
0

J'ai une requête très complexe dans PostgreSQL qui regroupe plusieurs tables, qui ont toutes un ensemble commun de champs que nous voulons union. Actuellement, nous sommes en train de générer cette requête. J'ai vu une solution à cela en utilisant UNPIVOT et je me demande s'il est possible de le faire dans la version SQL de PostgreSQL.Simplifier l'union complexe tout dans PostgreSQL

Ce que j'est quelque chose comme

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 

Je voudrais avoir des noms de tables à l'union dans le tableau séparé et utiliser pour cette requête.

PS. Changer de schéma n'est pas une option.

+2

sonne comme une mauvaise conception de base de données. :(Bonne chance! –

+0

Eh bien, j'ai simplifié, beaucoup de choses en dépendent, et il n'y a qu'un petit ensemble de colonnes qui se chevauchent dont j'ai besoin en union pour rassembler des statistiques: – Marcin

Répondre

3

Utilisez l'héritage pour la documentation Postgres pour inheritance. Vous aurez besoin de recréer la base de données, mais c'est facile si vous videz les tables sans schéma, créez un nouveau schéma avec l'héritage, et chargez les données en arrière.

Le schéma ressemblerait à quelque chose comme ceci:

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

, vous pouvez faire une sélection simple:

SELECT * FROM base; 

Ceci renverra toutes les lignes de base et toutes les tables héritant de base.

Lisez à propos de la table PostgreSQL partitioning à partir des documents si vous ne l'avez pas déjà fait.

+0

Le partitionnement est super. mises à jour en opérant simplement sur la table parent. – mikelikespie

2

Si vous ne pouvez vraiment pas corriger votre conception (ou ne voulez pas utiliser la très bonne suggestion de jmz), votre seul choix est probablement une fonction de retour ensemble qui construit l'UNION nécessaire "à la volée" puis renvoie les résultats de cela.

 
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; 

La fonction builds l'UNION nécessaire sur la base des noms de table dans union_source et exécute alors l'union et renvoie le résultat.

Vous pouvez étendre la table union_source pour stocker également la liste des colonnes pour chaque table, si les colonnes n'ont pas toujours le même nom.

Pour utiliser cette fonction, sélectionnez simplement de celui-ci:

 
select * 
from my_union()