查询 - 日期作为列 header

Query - Date as a column header

我有这个查询 returns 结果是这样的:

查询

select 
   d.veiculo, d.data_op, d.total_custo_op
from 
   fato_distribuicao d
left join dim_frota f 
   on d.veiculo = f.placa
left join schema_staging.staging_rotas_percorridas p 
   on p.placa = d.veiculo and p.data_operacao = d.data_op
where 
   d.uneg_dist = 'RJA'
   and d.data_op between '2016-07-18' and '2016-07-23'
   and f.tipo1 = 'AGREGADO'
group by d.veiculo, d.data_op, d.total_custo_op, p.setor
order by d.veiculo, d.data_op;

结果

veiculo data_op     total_custo_op

BTB7632 2016-07-19  219
BTB7632 2016-07-21  150
BTB7632 2016-07-22  176
DMI1082 2016-07-18  150
DMI1082 2016-07-19  168
DMI1082 2016-07-20  136
DMI1082 2016-07-21  163
DMI1082 2016-07-22  184
EJC1713 2016-07-18  205
EJC1713 2016-07-19  185
EJC1713 2016-07-20  190
EJC1713 2016-07-21  200
EJC1713 2016-07-22  179
GZG1647 2016-07-18  248
GZG1647 2016-07-20  279
GZG1647 2016-07-21  276
GZG1647 2016-07-22  314
GZG1647 2016-07-23  188

但我需要转换此结果并使用日期范围作为列 header 和 total_custo_op 作为数据来呈现此查询,如下所示:

预计

veiculo 2016-07-18  2016-07-19  2016-07-20  2016-07-21  2016-07-22  2016-07-23
BTB7632 null        219         null        150         176         null
DMI1082 150         168         136         163         184         null
EJC1713 205         185         190         200         179         null
GZG1647 248         null        279         276         314         188

我用 ARRAY_AGG 进行了数据透视查询,但我只能将日期作为数据分开。而且我不能使用 tablefunc 模块。

修复基础查询

首先,您的查询有问题。你有一个LEFT JOIN,然后是一个WHERE条件,那是胡说八道。

如果您确实需要 LEFT JOIN,请将条件 f.tipo1 = 'AGREGADO' 移至连接子句。但这在您的查询中没有意义。相反,使用普通的 JOIN.

p.setor添加到GROUP BY而你没有在结果中显示它是胡说八道。实际上, GROUP BY 在您的查询中根本没有任何意义,因为您没有聚合任何东西。您可能正在寻找 DISTINCTDISTINCT ON?

  • Select first row in each GROUP BY group?

所以:

SELECT d.veiculo, d.data_op, d.total_custo_op
FROM   fato_distribuicao d
JOIN   dim_frota         f ON f.placa = d.veiculo
LEFT   JOIN schema_staging.staging_rotas_percorridas p ON p.placa = d.veiculo
                                                      AND p.data_operacao = d.data_op
WHERE  d.uneg_dist = 'RJA'
AND    d.data_op BETWEEN '2016-07-18' AND '2016-07-23'
AND    f.tipo1 = 'AGREGADO'
-- GROUP  BY d.veiculo, d.data_op, d.total_custo_op  -- , p.setor  -- ??
ORDER  BY d.veiculo, d.data_op;

枢轴解决方案

要在没有 crosstab() 的情况下转换 ,您可以像这样在 CASE 语句上使用聚合:

SELECT veiculo
     , min(CASE WHEN data_op = '2016-07-18' THEN total_custo_op END) AS "2016-07-18"
     , min(CASE WHEN data_op = '2016-07-19' THEN total_custo_op END) AS "2016-07-19"
     , -- etc.
FROM  (
  <query from above>
   ) sub
GROUP  BY 1;

crosstab() 会更快更优雅,不过:

  • PostgreSQL Crosstab Query