【问题标题】:MySql - Update the status of rows using FIFO logicMySql - 使用 FIFO 逻辑更新行的状态
【发布时间】:2021-04-08 13:26:32
【问题描述】:

我有下面的 mysql 表,如果传递的数量大于使用 MySql 或 PHP 的 qty_req 值,我想用 1 更新多行 approval_status 字段。

申请表:

id part_id qty_req approval_status
1 16 20 0
2 17 30 0
3 16 40 0
4 17 50 0
5 17 60 0

例子:

$update_status=Array ( 
    [0] => Array ( [part_id] => 17 [qty] => 90 )
    [1] => Array ( [part_id] => 16 [qty] => 70 ) 
)

从上面的数组中,90 是part_id 17 的可用数量。我想将requisition 表中part_id 为17 的行更新为approval_status 为1,并具有以下场景:

  1. 将approval_status 更新为1,因为part_id 17 的第一行的数量是30,小于90。

  2. 将approval_status 更新为1,因为part_id 17 的第二行的数量是30+50=80,小于90。

  3. 第三行不会更新,因为30+50+60=140 的总数大于 90。

很遗憾,我找不到任何教程来实现这一点。

任何帮助将不胜感激。提前致谢。

【问题讨论】:

  • 您的表中没有任何东西可以设置明确的行顺序。所以术语“第一行”、“下一行”等等 - 不存在。视觉位置排序是假的。现在任务无法解决。
  • 为了做你想做的事,你必须有一个可靠的列进行排序——比如创建日期或任何对你的业务有意义的东西。

标签: php mysql codeigniter


【解决方案1】:

单个数据:

UPDATE test t1
NATURAL JOIN ( SELECT *, SUM(qty_req) OVER (ORDER BY reg_date) cum_sum
               FROM test
               WHERE part_id = @part_id ) t2
SET t1.approval_status = 1 
WHERE cum_sum <= @qty;

多个数据:

UPDATE test t1
NATURAL JOIN ( SELECT test.*, 
                      SUM(qty_req) OVER (PARTITION BY part_id ORDER BY reg_date) cum_sum,
                      qty
               FROM test
               JOIN JSON_TABLE(@json,
                               '$[*]' COLUMNS ( part_id INT PATH '$.part_id',
                                                qty INT PATH '$.qty')) jsontable USING (part_id) ) t2
SET t1.approval_status = 1 
WHERE cum_sum <= qty;

https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=7cf062d81a138657dee78f3026623783

添加了列reg_date 和唯一索引以提供明确且明确的行排序。


适用于 MySQL 5.6 的解决方案:

UPDATE test t1
NATURAL JOIN ( SELECT t1.part_id,
                      t1.qty_req,
                      t1.approval_status,
                      t1.reg_date,
                      SUM(t2.qty_req) cum_sum
               FROM test t1
               JOIN test t2 USING (part_id)
               WHERE t1.reg_date >= t2.reg_date
               GROUP BY t1.part_id,
                        t1.qty_req,
                        t1.approval_status,
                        t1.reg_date ) t2
JOIN ( SELECT 17 part_id, 90 qty
       UNION ALL
       SELECT 16, 50 ) t3 USING (part_id)
SET t1.approval_status = 1 
WHERE t2.cum_sum <= t3.qty

https://dbfiddle.uk/?rdbms=mysql_5.6&fiddle=0aad358941f66d1f385799072237d513

源数据必须以查询文本的形式形成 - 请参阅子查询 t3。

【讨论】:

  • 感谢您的回答。是否可以在同一个查询中传递多个带有数量的 part_id?示例:而不是 @part_id,(16,17) 两个 part_id 的数量
  • 将此多数据解析为每行一个part_id 的行集,并在查询的行源中使用它而不是UDV -- 你能粘贴格式吗?我将按此生成行集。
  • 你能在答案查询中更新这个吗?我不确定如何将上述格式传递给 mysql 查询。
  • #1064 - 您的 SQL 语法有错误;检查与您的 MariaDB 服务器版本相对应的手册,以在第 6 行的 '(@json, '$[*]' COLUMNS ( part_id INT PATH '$....' ) 附近使用正确的语法 - 运行时出现此错误数据库中的代码。
  • 埃文 我直接这样尝试过,但同样的错误 - JOIN JSON_TABLE('[{"part_id":17,"qty":90},{"part_id":16,"qty":50 }]', '$[*]'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-29
  • 1970-01-01
  • 2019-03-17
  • 1970-01-01
  • 1970-01-01
  • 2021-04-01
  • 1970-01-01
相关资源
最近更新 更多