在PostgreSQL中简化复杂的联合

时间:2010-08-13 23:39:54

标签: postgresql select union

我在PostgreSQL中有非常复杂的查询,它会联合几个表,这些表都有我们想要联合的通用字段集。目前我们正在预生成此查询。我已经看到使用UNPIVOT解决这个问题了,我想知道是否可以在PostgreSQL的SQL风格中做到这一点。

我所拥有的是像

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 :(得分:3)

inheritance的Postgres文档使用继承。您需要重新创建数据库,但如果您在没有模式的情况下转储表,使用继承创建新模式并重新加载数据,这很容易。

架构看起来像这样:

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

使用此设计,您可以进行简单的选择:

SELECT * FROM base;

这将返回base中的所有行以及继承自base的所有表。

如果您还没有这样做,请从文档中了解PostgreSQL表partitioning

答案 1 :(得分: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,然后执行union并返回结果。

如果列不总是具有相同的名称,您可以扩展union_source表以存储每个表的列列表。

要使用此功能,只需从中选择:

select *
from my_union()