使用条件和分组依据查找累计总数

Finding cumulative totals with condition and group by

这是我的案例:

我想计算给定商品在任何给定日期的数量和价格。

价格是根据商品总数量和单价计算得出的,因此价格会根据商品的数量而变化。

warehouse_1 表示该项目是从该仓库发货的,warehouse_2 表示该项目已发送到该仓库。

这是我的逻辑:

获取每个项目的交付并计算它们的数量。 (第一个 CTE)

分别求出两个仓库的数量总和。 (第二届 CTE)

计算最终数量并将其乘以单价。

显示由商品编号、数量和价格组成的结果。

我编写了一个可以正确计算的查询,但是当数据量变大时,它的速度会呈指数级下降。 (在我的 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;

`

很难说没有 MCV, but my guess on what you are trying to do is do a Windowed SUM() calculation as opposed to LAG(). There is documentation 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