Postgresql:无法在FROM ...处使用子查询获取结果

时间:2012-12-17 14:20:05

标签: postgresql

我要完成的是通过内部SQL中的所有表获取sendercompidtargetcompidmsgtype的所有唯一组合的聚合数据。

我希望在输出结果中有20mil到40mil的唯一行。

我无法在Postgresql 8.3.13上运行下一个查询:

SELECT 
    sendercompid, targetcompid, count(msgtype), msgtype 
FROM 
    (SELECT table_name 
     FROM information_schema.tables 
     WHERE table_catalog = 'test' 
       AND table_schema = 'msg' 
       AND (table_name like 'fix_aee_20121214%') OR 
           (table_name like 'fix_aee2_20121214%')
   ) 
WHERE 
    (sendercompid LIKE '%201%') OR 
    (targetcompid LIKE '%201%') 
GROUP BY 
    sendercompid, targetcompid, msgtype ;

如果在2:外部和内部分割此选择,则: inner将提供表的列表,outer将从每个表中进行选择和分组。

如果我将这两个SQL作为一个运行,我的pgsql db

会出现别名错误
  

错误:FROM中的子查询必须具有别名

我尝试使用别名,但此错误不会消失。

有什么想法我在那里失踪了吗?

谢谢。

4 个答案:

答案 0 :(得分:1)

FROM不会像您认为的那样起作用。子选择与任何其他查询一样:它生成一组行。外部SELECT与这些行一起工作,就像它们是一个表一样。除此之外没有特别的魔力;它不知道您返回的值是表名,也不会将它们视为表。

你可以使用目录表完成你想要的东西,但这很复杂而且很糟糕。

由于您的子表似乎是基于日期的分区,我认为您真正想要使用的是Postgres内置的分区支持,描述为in these docs。基本上,您的分区从父表继承,并为每个子设置范围约束。当您从启用了constraint_exclusion的父表进行查询时,Postgres会自动选择适当的分区。

答案 1 :(得分:1)

您可以使用动态SQL“运行”此类查询。想法 - 在PL \ pgSQL过程中使用表名作为字符串形成正确的查询,并EXECUTE。类似的东西:

CREATE OR REPLACE FUNCTION public.function1 (
)
RETURNS TABLE (
  "field1" NUMERIC,
  "field2" NUMERIC,
  ...
) AS
$body$
BEGIN
 RETURN EXECUTE 'SELECT * FROM '|| (SELECT table_name from information_schema.tables 
              where table_catalog = 'test' AND 
                    table_schema='msg' AND
                    (table_name like 'fix_aee_20121214%') OR 
                    (table_name like 'fix_aee2_20121214%')); 
END;
$body$
LANGUAGE 'plpgsql';

然后使用类似的东西:

SELECT sendercompid, targetcompid, count(msgtype), msgtype 
       FROM  function1
       WHERE (sendercompid LIKE '%201%') OR 
             (targetcompid LIKE '%201%') 
       GROUP BY sendercompid, targetcompid, msgtype ;

或者您可以创建具有完整查询和一些参数的函数来构建WHERE子句。

详细信息:EXECUTE

答案 2 :(得分:0)

如果这只是一个概念,那么:

  1. ERROR: subquery in FROM must have an alias
  2. 没有列sendercompid, targetcompid, count(msgtype), msgtype来自哪里的信息。

    SELECT sendercompid,targetcompid,count(msgtype),msgtype from(    来自information_schema.tables的SELECT table_name           table_catalog ='test'AND                 table_schema ='msg'AND                 (table_name类似'fix_aee_20121214%')或                 (table_name类似'fix_aee2_20121214%')    ) 一个    WHERE(sendercompid LIKE'%201%')或          (targetcompid LIKE'%201%')    GROUP BY sendercompid,targetcompid,msgtype;

答案 3 :(得分:-1)

使用子查询的别名。更好地为所有表格设置别名以避免混淆。