SQLITE从库存中更新多个行,其中我们有一个具有多个记录产品

z2acfund  于 2022-12-13  发布在  SQLite
关注(0)|答案(1)|浏览(138)

我想为产品表创建一个触发器,以便在销售产品后更新数量。
我有一个类似下面productTB产品表,其中包含名称和数量字段:
| 名称|数量|
| - -|- -|
| '甲'|一个|
| 'B'|四个|
| '甲'|四个|
我想写一个查询删除2数量为'A'项目。
我希望'A'项目的数量如下
| 名称|数量|
| - -|- -|
| '甲'|第0页|
| 'B'|四个|
| '甲'|三个|
如何在SQLite中做到这一点?

u3r8eeie

u3r8eeie1#

假设业务规则是从最少数量中扣除库存,并且产品'A'的库存如下:

name|qty|
----+---+
A   |  1|
A   |  3|
A   |  5|
A   |  7|
A   |  9|

现在销售了8种产品“A”,我们需要按以下顺序扣除库存:

name|qty| qty to be deducted|balance|
----+---+-------------------+-------+
A   |  1|                  1|      0|
A   |  3|                  3|      0|
A   |  5|                  4|      1|
A   |  7|                  0|      7|
A   |  9|                  0|      9|

第一步、用窗口函数计算产品A的累计数量:

select name,
       qty,
       sum(qty) over (partition by name order by qty) as c_qty
  from ka
 where name = 'A';

我们得到:(cqty为累计数量)

name|qty|cqty|
----+---+----+
A   |  1|   1|
A   |  3|   4|
A   |  5|   9|
A   |  7|  16|
A   |  9|  25|

第二步,所以我们需要从前三行分配/扣除库存数量,但是有多少呢?我们来计算一下:

with cte_inv as (
select name,
       qty,
       sum(qty) over (partition by name order by qty) as cqty
  from ka
 where name = 'A')
select name,
       qty,
       cqty,
       case when cqty < 8 then qty else qty - (cqty - 8) end as aqty
  from cte_inv
 where aqty >=0;

得到:(aqty为分配/扣除数量)

name|qty|cqty|aqty|
----+---+----+----+
A   |  1|   1|   1|
A   |  3|   4|   3|
A   |  5|   9|   4|

第三步现在我们知道(aqty)从产品'A'库存中扣除,我们可以更新该表。但是,在此之前,我们需要能够单独标识每一行。该表架构没有主键。我们可以做的是利用sqlite的rowid功能,它是表中每一行的唯一标识符。在本例中,我们从产品库存表中进行选择:

select rowid, * from ka;

然后,我们得到以下结果:

rowid|name|qty|
-----+----+---+
    1|A   |  1|
    2|A   |  3|
    3|A   |  5|
    4|A   |  7|
    5|A   |  9|

好的,我们有一个唯一的键来标识每一行,我们可以继续并相应地更新表,方法是将上述查询作为CTE(Common Table Express)合并到一个查询中,如下所示:

with cte_inv as (
select rowid as pkey,
       name,
       qty,
       sum(qty) over (partition by name order by qty) as cqty
  from ka
 where name = 'A'),
cte_ainv as (
select pkey,
       name,
       qty,
       cqty,
       case when cqty < 8 then qty else qty - (cqty - 8) end as aqty
  from cte_inv
 where aqty >=0)
update ka
   set qty = qty - (select aqty from cte_ainv where pkey = ka.rowid)
 where rowid <= (select max(pkey) from cte_ainv);

select * from ka;

结果:

name|qty|
----+---+
A   |  0|
A   |  0|
A   |  1|
A   |  7|
A   |  9|

现在您可以看到清单已正确更新。
本练习中介绍了一些概念:

  • 获取累计数量的窗口函数:sum() over (partition by name order by qty) as city
  • 公用表表达式(CTE)
  • rowid作为主键。

建议:修改表架构以定义主键。在sqlite3中,我们可以使用rowid来解决设计问题。但是,这不是最佳实践。

相关问题