查询 - 日期作为列 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
在您的查询中根本没有任何意义,因为您没有聚合任何东西。您可能正在寻找 DISTINCT
或 DISTINCT 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
我有这个查询 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
在您的查询中根本没有任何意义,因为您没有聚合任何东西。您可能正在寻找 DISTINCT
或 DISTINCT 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