每行的不同条件求和

Sum with different condition for every line

在我的 Postgresql 9.3 数据库中,我有一个 table stock_rotation:

+----+-----------------+---------------------+------------+---------------------+
| id | quantity_change | stock_rotation_type | article_id |        date         |
+----+-----------------+---------------------+------------+---------------------+
|  1 |              10 | PURCHASE            |          1 | 2010-01-01 15:35:01 |
|  2 |              -4 | SALE                |          1 | 2010-05-06 08:46:02 |
|  3 |               5 | INVENTORY           |          1 | 2010-12-20 08:20:35 |
|  4 |               2 | PURCHASE            |          1 | 2011-02-05 16:45:50 |
|  5 |              -1 | SALE                |          1 | 2011-03-01 16:42:53 |
+----+-----------------+---------------------+------------+---------------------+

类型:

在此实现中,要获取某件商品的当前库存价值,您需要汇总自特定商品最近 INVENTORY 以来的所有数量变化(包括库存价值)。我不知道为什么要这样实现,不幸的是现在很难改变它。

我现在的问题是如何同时对多篇文章执行此操作。

我最近的尝试是这样的:

WITH latest_inventory_of_article as (
    SELECT MAX(date)
    FROM stock_rotation
    WHERE stock_rotation_type = 'INVENTORY'
)
SELECT a.id, sum(quantity_change)
FROM stock_rotation sr
INNER JOIN article a ON a.id = sr.article_id
WHERE sr.date >= (COALESCE(
                     (SELECT date FROM latest_inventory_of_article),
                     '1970-01-01'
                 ))
GROUP BY a.id

但是每篇文章的 INVENTORY 类型的最新 stock_rotation 的日期可能不同。 我试图避免循环遍历多个文章 ID 来查找此日期。

您可以将 DISTINCT ONORDER BY 一起使用以获得 WITH 子句中每个 article_id 的最新 INVENTORY 行。

然后您可以将其与原始 table 连接起来以获取所有后面的行并添加值:

WITH latest_inventory as (
    SELECT DISTINCT ON (article_id) id, article_id, date
    FROM stock_rotation
    WHERE stock_rotation_type = 'INVENTORY'
    ORDER BY article_id, date DESC
)
SELECT article_id, sum(sr.quantity_change)
FROM stock_rotation sr
    JOIN latest_inventory li USING (article_id)
WHERE sr.date >= li.date
GROUP BY article_id;

以下是我的看法:首先,使用 window 函数构建处于最后库存状态的产品列表。然后,将其加入到整个列表中,过滤晚于项目库存日期的操作。

with initial_inventory as
(
select article_id, date, quantity_change from
(select article_id, date, quantity_change, rank() over (partition by article_id order by date desc)
from stockRotation
where type = 'INVENTORY'
) a
where rank = 1
)
select ii.article_id, ii.quantity_change + sum(sr.quantity_change)
from initial_inventory ii
join stockRotation sr on ii.article_id = sr.article_id and sr.date > ii.date
group by ii.article_id, ii.quantity_change

在这种情况下,我将使用不同的内部查询来获取每篇文章的最大库存。您有效地使用了 stock_rotation 两次,但它应该可以工作。如果 table 太大,您可以尝试其他方法:

SELECT sr.article_id, sum(quantity_change)
FROM stock_rotation sr
LEFT JOIN (
    SELECT article_id, MAX(date) AS date
    FROM stock_rotation
    WHERE stock_rotation_type = 'INVENTORY'
    GROUP BY article_id) AS latest_inventory
    ON latest_inventory.article_id = sr.article_id
WHERE sr.date >= COALESCE(latest_inventory.date, '1970-01-01')
GROUP BY sr.article_id