这是我的情况:
我想计算给定日期的给定项目的数量和价格。
价格是使用总商品数量和单价计算得出的,因此价格会随商品数量而变化。
warehouse_1
指出该物品是从该仓库发货的,warehouse_2
指出该物品已发送到该仓库。
这是我的逻辑:
获取每个项目的交货并汇总其数量。 (第一CTE)
分别查找两个仓库中的数量总和。 (第二CTE)
计算最终数量,然后乘以单价。
显示结果,其中包含商品ID,数量和价格。
我编写了一个查询,该查询可以正确执行计算,但是当数据数量增加时,它会以指数形式变慢。 (在具有6k行的数据库上花费5秒,几乎将数据库锁定在具有21k行的同事数据库上)
如何优化此查询?我正在对来自第一CTE的每一行进行第二CTE的累积计算,我认为需要进行返工。
我可以使用
LAG()
此用例的功能?我用
LAG(a.deliveryTotal) over(order by a.updated desc rows between unbounded preceding and current row)
而不是第二CTE中的CASE块,但是我似乎无法弄清楚如何使用filter()
或在LAG()语句中放置条件。
这是我的查询:
`
with deliveriesCTE as (
select
row_number() over(partition by it.id
order by
dd.updated asc) as rn,
sum(dd.quantity) as deliveryTotal,
dd.updated as updated,
it.id as item_id,
d.warehouse_1 as outWH,
d.warehouse_2 as inWH,
d.company_code as company
from
deliveries d
join deliveries_detail dd on
dd.deliveries_id = d.id
join items it on
it.id = dd.item_id
where
...
group by
dd.updated,
it.id,
d.warehouse_1,
d.warehouse_2,
d.company_code
order by
dd.updated asc),
cumulativeTotalsByUnit as (
select
distinct on
(a.item_id) a.rn,
a.deliveryTotal,
a.updated,
a.item_id,
a.outWH,
a.inWH,
a.company,
case
when a.rn = 1
and a.outWH is not null then coalesce(a.deliveryTotal,
0)
else (
select
coalesce(sum(b.deliveryTotal) filter(
where b.outWH is not null),
0)
from
deliveriesCTE b
where
a.item_id = b.item_id
and b.rn <= a.rn)
end as outWHTotal,
case
when a.rn = 1
and a.inWH is not null then coalesce(a.deliveryTotal,
0)
else (
select
coalesce(sum(b.deliveryTotal) filter(
where b.inWH is not null),
0)
from
deliveriesCTE b
where
a.item_id = b.item_id
and b.rn <= a.rn)
end as inWHTotal
from
deliveriesCTE a
order by
a.item_id,
a.updated desc)
select
resultView.item_id,
resultView.quantity,
resultView.price
from
(
select
cumTotals.item_id,
cumTotals.inWHTotal - cumTotals.outWHTotal as quantity,
p.price * (cumTotals.inWHTotal - cumTotals.outWHTotal) as price
from
prices p
join cumulativeTotalsByUnit cumTotals on
cumTotals.item_id = p.item_id ) resultView
where
resultView.rn = 1;
`
答案 0 :(得分:1)
很难说不使用MCV,但我对您要执行的操作的猜测是执行Windowed SUM()计算而不是LAG()。有文档Here。
查询cumulativeTotalsByUnit
并不是必需的,并且可以二次执行复杂的自引用联接。
您的交付CTE应该如下:
select
sum(dd.quantity) over (partition by it.id ORDER BY dd.updated asc) as deliveryTotal,
dd.updated as updated,
it.id as item_id,
d.warehouse_1 as outWH,
d.warehouse_2 as inWH,
d.company_code as company
from
deliveries d
join deliveries_detail dd on
dd.deliveries_id = d.id
join items it on
it.id = dd.item_id
where
...
group by
dd.updated,
it.id,
d.warehouse_1,
d.warehouse_2,
d.company_code
order by
dd.updated asc