将两个查询与月平均值相结合

时间:2016-06-25 21:18:10

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

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

"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;

2 个答案:

答案 0 :(得分: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;

在聚合之后加入比以前更快(加入操作次数更少)。

GROUP BY JOINORDERtimestamp text值比to_char()再现更快。通常也更清晰,更不容易出错(尽管在这种特殊情况下文本是明确的)。这就是为什么我在较低级别使用date_trunc()而不是function TForm3.CreateVHDX(const AFilePath: string; const ASize: ULONG; const AType: integer; out AReturn: DWORD): Boolean; var params: TCreateVirtualDiskParameters; mask: TVIRTUAL_DISK_ACCESS_MASK; vst: TVirtualStorageType; hvhd: THandle; begin hVhd := INVALID_HANDLE_VALUE; // vst.DeviceId := VIRTUAL_STORAGE_TYPE_DEVICE_VHDX; vst.DeviceId := VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN; // vst.VendorId := VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT ; vst.VendorId := VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN; params.Version:= CREATE_VIRTUAL_DISK_VERSION_2; params.Version2.UniqueId := TGUID.Empty; params.Version2.MaximumSize:= ASize * 1024 * 1024; params.Version2.BlockSizeInBytes := CREATE_VIRTUAL_DISK_PARAMETERS_DEFAULT_BLOCK_SIZE; //0 params.Version2.SectorSizeInBytes := $200; params.Version2.PhysicalSectorSize := $200; params.Version2.ParentPath := nil; // params.Version2.OpenFlags := OPEN_VIRTUAL_DISK_FLAG_NONE; params.Version2.ResiliencyGuid := TGUID.Empty; // params.Version2.ParentVirtualStorageType := ; mask := VIRTUAL_DISK_ACCESS_NONE; if AType = 0 then //dynamic begin AReturn := CreateVirtualDisk( @vst, PWideChar(AFilePath), mask, nil, CREATE_VIRTUAL_DISK_FLAG_NONE, 0, @params, nil, hvhd); Result := AReturn = ERROR_SUCCESS; end; if AType = 1 then //fixed begin AReturn := CreateVirtualDisk( @vst, PWideChar(AFilePath), mask, nil, CREATE_VIRTUAL_DISK_FLAG_FULL_PHYSICAL_ALLOCATION, 0, @params, nil, hvhd); Result := AReturn = ERROR_SUCCESS; end; if hvhd <> INVALID_HANDLE_VALUE then CloseHandle( hvhd ) end; 的原因。

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

类似案例有更多解释:

答案 1 :(得分:1)

这应该得到你所需要的。内部“PQ”(PreQuery)在每个可能的日期之间进行联合,但也添加了一个标志列来标识与之关联的平均值。每个部分按日期分组。所以现在,外部查询AT MOST在给定日期有2条记录......一条是税,另一条是文达。因此,现在您不需要任何完整的外部联接,也不需要构建一些动态日历数据,以获取所有可能日期的详细信息。

因此,可能只有税收平均值或Venda平均值或两者。

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