【问题标题】:Combine two queries with monthly average将两个查询与每月平均值相结合
【发布时间】:2016-06-25 21:18:10
【问题描述】:

我需要将这两个查询的结果放在一个具有以下结构的返回中:

"date", avg(selic."Taxa"), avg(titulos."puVenda")

表的部分结构:

selic
"dtFechamento" date,
"pTaxa" real

titulos
"dtTitulo" date,
"puVenda" real,
"nomeTitulo" character(30)

查询表selic

select to_char("dtFechamento", 'YYYY-MM') as data, avg("pTaxa")
from "selic"
group by data
order by data

查询表titulos

select to_char("dtTitulo", 'YYYY-MM') as data, avg("puVenda")
from "titulos"
where "nomeTitulo" = 'LFT010321'
group by data
order by data

我尝试了一个子查询,但它返回的字段彼此相邻,无法集合。

select *
from (select to_char("dtFechamento", 'YYYY-MM') as data, avg("pTaxa")
from "selic"
group by data
order by data) as selic,
(select to_char("dtTitulo", 'YYYY-MM') as data, avg("puVenda")
from "titulos"
where "nomeTitulo" = 'LFT010321'
group by data
order by data) as LFT010321;

【问题讨论】:

  • 如果只有一个查询一个月有结果,返回什么?另一个为NULL?在两个查询中没有结果的几个月之间怎么办?没有行(跳过一个月)?还是返回带有两个 NULL 值的月份?
  • 我冒昧地修正了您的姓名和双引号,这会分散您对实际问题的注意力。

标签: sql postgresql subquery aggregate full-outer-join


【解决方案1】:

假设您希望每月返回一行,其中两个查询中的任何一个都返回一行。并用 NULL 填充其他查询中的缺失值。

使用FULL [OUTER] JOIN

SELECT to_char(mon, 'YYYY-MM') AS data, s.avg_taxa, t.avg_venda
FROM  (
   SELECT date_trunc('month', "dtFechamento") AS mon, avg("pTaxa")   AS avg_taxa
   FROM   selic
   GROUP  BY 1
   ) s
FULL JOIN (
   SELECT date_trunc('month', "dtTitulo")     AS mon, avg("puVenda") AS avg_venda
   FROM   titulos
   WHERE  "nomeTitulo" = 'LFT010321'
   GROUP  BY 1
   ) t USING (mon)
ORDER  BY mon;

聚合之后加入比之前快很多(加入操作更少)。

timestamp 值上GROUP BYJOINORDER 也比在text 再现上更快。通常也更清晰,更不容易出错(尽管在这种特殊情况下文本是明确的)。这就是我在较低级别使用date_trunc() 而不是to_char() 的原因。

如果月份的格式不重要,您可以只返回时间戳值。否则,您可以在完成处理后以任何您喜欢的方式格式化。

更多解释的类似案例:

【讨论】:

    【解决方案2】:

    这应该可以满足您的需求。内部的“PQ”(PreQuery)在每个可能的日期之间进行联合,但还添加了一个标志列来标识它与哪个平均值相关联。每个部分都按日期分组。所以现在,外部查询将在给定日期最多有 2 条记录……一条用于税收,另一条是文达。因此,现在您不需要任何完整的外部联接,也不需要构建一些动态日历数据基础来获取所有可能日期的详细信息。

    因此,可能只有 Tax average 或 Venda average 或两者兼而有之。

    SELECT
          PQ.Data,
          SUM( CASE when PQ.SumType = 'T' then PQ.TypeAvg else 0 end ) as AvgTax,
          SUM( CASE when PQ.SumType = 'V' then PQ.TypeAvg else 0 end ) as AvgVenda
       from
          ( select 
                  to_char( dtFechamento, 'YYYY-MM') as data,
                  'T' as sumtype,
                  avg( pTaxa ) as TypeAvg
               from 
                  selic
               group by 
                  to_char( dtFechamento, 'YYYY-MM') as data
            UNION ALL
            select 
                  to_char( dtTitulo, 'YYYY-MM') as data, 
                  'V' as sumType,
                  avg( puVenda ) as TypeAvg
               from
                  titulos
               where 
                  nomeTitulo = 'LFT010321'
               group by 
                  to_char( dtTitulo, 'YYYY-MM') ) PQ
       group by
          PQ.Data
       order by
          PQ.Data
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多