2014-02-07 61 views
1

我有以下查询返回两个不同表中基本上唯一的行 的最小值,最大值和用户总数。使用查询结果设置下一个查询的表

select sum(user_count) as user_count_sum, sum(min_count) as min_count_sum, 
sum(max_count) as max_count_sum 
from(
select max(case when di = 'i' then di_count end) as user_count, 
     min(di_count) as min_count, 
     max(di_count) as max_count 
from (
    select di, 
      count(distinct rt) as di_count 
    from gpstablev2 
    where rt > GETDATE() - '1 day'::INTERVAL 
    group by di 
) 
UNION 
select max(case when di = 'i' then di_count end) as user_count, 
     min(di_count) as min_count, 
     max(di_count) as max_count 
from (
    select di, 
      count(distinct rt) as di_count 
    from powertablev2 
    where rt > GETDATE() - '1 day'::INTERVAL 
    group by di 
) 
) 

现在我也有一个主表,如果我要运行下面的查询将改为返回以下

select table from mastertable; 

gpstablev2 
powertablev2 
...(more table names) 

粘贴9个UNION块喜欢的人我来总结所有在mastertable中列出的表,有没有办法我可以使用查询mastertable来清理呢?

如果我在java中这样做,我会先从主表中获取我的ResultSet,然后自己做10个查询和UNION。但我宁愿让我的数据库完成所有处理,并且能够根据mastertable的内容进行更新。

编辑: 意见的基础上,我想一个动态查询,远远已经得到了这一点,但我仍然有问题放在一起件

CREATE OR REPLACE FUNCTION get_sums() 
RETURNS TABLE(user_count_sum bigint, min_count_sum bigint, max_count_sum bigint) 
$BODY$ 
BEGIN 

RETURN QUERY EXECUTE " 
SELECT $$SELECT sum(user_count) AS user_count_sum 
     ,sum(min_count) AS min_count_sum 
     ,sum(max_count) AS max_count_sum 
FROM (
    SELECT max(case when di = 'id' then di_count end) AS user_count 
     ,min(di_count) AS min_count 
     ,max(di_count) AS max_count 
    FROM ($$ 
|| 
string_agg(format($$ 
     (SELECT di, count(distinct rt) AS di_count 
     FROM %I 
     WHERE rt > now() - interval '1 day' 
     GROUP BY 1)$$, tbl) 
     ,' 

     UNION ALL') 
|| ' 
    ) sub1 
    ) sub2' 
FROM mastertable; 
INTO results_var" 

END; 
$BODY$ 
LANGUAGE plpqsql; 
+0

你可以用PL/pgSQL函数内的动态SQL(谷歌的'EXECUTE')。 –

+0

我看到只是寻找更多方向如何执行动态SQL。试图从这个例子学习 http://stackoverflow.com/questions/12028041/select-a-dynamic-set-of-columns-from-a-table-and-get-the-sum-for-each/12031145 #12031145 –

+1

类型定义丢失。应该是:'RETURNS TABLE(user_count_sum bigint,min_count_sum bigint,max_count_sum bigint)''。快速浏览其余部分看起来不错。 –

回答

0

其余您需要为动态SQL。 SQL不接受文字/值到标识符的动态转换。所以你需要先建立查询然后执行它。为此,您可以在您的客户端(好像是Java的),或者做所有内Postgres的,这通常是最快的:

SELECT $$SELECT sum(user_count) AS user_count_sum 
     ,sum(min_count) AS min_count_sum 
     ,sum(max_count) AS max_count_sum 
FROM (
    ($$ 
|| 
string_agg(format($$ 
    SELECT max(case when di = 'i' then di_count end) AS user_count 
     ,min(di_count) AS min_count 
     ,max(di_count) AS max_count 
    FROM (
     SELECT di, count(distinct rt) AS di_count 
     FROM %I 
     WHERE rt > now() - interval '1 day' 
     GROUP BY 1 
    ) t 
    )$$, tbl) 
     ,' 

    UNION ALL 
    (') 
|| ' 
    ) sub' 
FROM mastertable; 

主要生产的查询字符串:

SELECT sum(user_count) AS user_count_sum 
     ,sum(min_count) AS min_count_sum 
     ,sum(max_count) AS max_count_sum 
FROM (
    (
    SELECT max(case when di = 'i' then di_count end) AS user_count 
     ,min(di_count) AS min_count 
     ,max(di_count) AS max_count 
    FROM (
     SELECT di, count(distinct rt) AS di_count 
     FROM gpstablev2 
     WHERE rt > now() - interval '1 day' 
     GROUP BY 1 
    ) t 
    ) 

    UNION ALL 
    (
    SELECT max(case when di = 'i' then di_count end) AS user_count 
     ,min(di_count) AS min_count 
     ,max(di_count) AS max_count 
    FROM (
     SELECT di, count(distinct rt) AS di_count 
     FROM powertablev2 
     WHERE rt > now() - interval '1 day' 
     GROUP BY 1 
    ) t 
    ) 

    UNION ALL 
    ... 

    ) sub; 
  • GETDATE()不是有效的Postgres函数。您可能的意思是now()CURRENT_DATE ..取决于未公开的类型rt。我改用now()

  • 您可能想要使用UNION ALL而不是UNION此处。

  • 还修复了子查询缺少的别名并做了一些小的简化。

包装这与EXECUTE一个PLPGSQL功能。有plenty of closely related examples here on SO与代码和链接和解释...

+1

您的查询与有问题的查询有所不同。您需要将最大/最小聚合移动到每个子查询。 –

+0

@IgorRomanchenko:好的,谢谢。一个查询级别是歪斜的。 –

相关问题