如何使用 MySQL 中的嵌套查询 SELECT 和 INSERT 直到订购数量完成
How to SELECT and INSERT until ordered quantity is completed using nested query in MySQL
查看上图我想 运行 我的查询,直到满足 $orderQty
。在图片中,上面的 table 是 products
,下面的 table 是 temp_salesee
,这是 运行 宁我的代码后的结果。
这是我的代码:
$orderQty = 22;
$trID = round(microtime(true) * 1000);
$proID = 1;
$con->begin_transaction();
$stmt = $con->prepare("
INSERT INTO `temp_salesee` (
SELECT
null,
$trID,
`pid`,
`pur_price`,
(CASE
WHEN qty_avbl <= $orderQty THEN qty_avbl
WHEN qty_avbl >= $orderQty THEN $orderQty
else 0
END),
`batch_number`
FROM `products`
WHERE `pid` = ?
ORDER BY `batch_number` ASC
)
");
$stmt->bind_param('s', $proID);
$stmt->execute();
$con->commit();
在 temp_salesee
中,第 3 行 qty
应为 2,以便总数 qty
等于 $orderQty
此时查询应停止,第 4、5 行不应插入。如果 $orderQty
小于 qty_avbl
,如 products
table 的第一行所示,则仅应在 temp_salesee
[=34= 中插入第一行] 有 qty
的 5.
谢谢
老实说,我只想放弃使用“智能查询”的想法,而使用普通的编程循环。 “完成。” 准备 SELECT
和 INSERT
语句句柄,开始事务,运行 SELECT
。然后,INSERT
多次。最后,COMMIT
.
虽然毕竟可能有一种“聪明”的方法来做到这一点,但它可能不值得寻找。而且,它可能不会 显而易见, 这可能意味着很难按照要求继续前进 (不可避免地...) 改变。所以,我会说,“减少你的损失。”
我希望并想象一定有一个更高效的解决方案,但无论如何,请考虑以下几点:
架构 (MySQL v8.0)
DROP TABLE IF EXISTS product_batches;
CREATE TABLE product_batches
(batch_number SERIAL PRIMARY KEY
,product_id INT NOT NULL
,quantity_available INT NOT NULL
);
INSERT INTO product_batches VALUES
( 1,1,15),
( 3,1, 5),
( 7,1,20),
(10,1,30),
(11,1,50);
查询#1
SELECT batch_number
, product_id
FROM
( SELECT x.*
, COALESCE(LAG(SUM(y.quantity_available),1) OVER (ORDER BY batch_number),0) running
FROM product_batches x
JOIN product_batches y
ON y.product_id = x.product_id
AND y.batch_number <= x.batch_number
GROUP
BY x.batch_number
) a
WHERE running <=22;
batch_number
product_id
1
1
3
1
7
1
编辑:
没有广泛测试,但对于旧版本,我认为你可以这样做(虽然性能可能很糟糕),所以认真考虑升级:
SELECT x.*
, z.total - SUM(y.quantity_available) running
FROM product_batches x
JOIN product_batches y
ON y.product_id = x.product_id
AND y.batch_number >= x.batch_number
JOIN (SELECT product_id, SUM(quantity_available) total FROM product_batches GROUP BY product_id) z
ON z.product_id = x.product_id
GROUP
BY x.batch_number
HAVING running <= 22;
编辑 2:
也许这样更清楚:
SELECT x.*
, GREATEST(SUM(y.quantity_available)-22,0) balance
FROM product_batches x
JOIN product_batches y
ON y.product_id = x.product_id
AND y.batch_number <= x.batch_number
GROUP
BY x.batch_number
HAVING balance < quantity_available
查看上图我想 运行 我的查询,直到满足 $orderQty
。在图片中,上面的 table 是 products
,下面的 table 是 temp_salesee
,这是 运行 宁我的代码后的结果。
这是我的代码:
$orderQty = 22;
$trID = round(microtime(true) * 1000);
$proID = 1;
$con->begin_transaction();
$stmt = $con->prepare("
INSERT INTO `temp_salesee` (
SELECT
null,
$trID,
`pid`,
`pur_price`,
(CASE
WHEN qty_avbl <= $orderQty THEN qty_avbl
WHEN qty_avbl >= $orderQty THEN $orderQty
else 0
END),
`batch_number`
FROM `products`
WHERE `pid` = ?
ORDER BY `batch_number` ASC
)
");
$stmt->bind_param('s', $proID);
$stmt->execute();
$con->commit();
在 temp_salesee
中,第 3 行 qty
应为 2,以便总数 qty
等于 $orderQty
此时查询应停止,第 4、5 行不应插入。如果 $orderQty
小于 qty_avbl
,如 products
table 的第一行所示,则仅应在 temp_salesee
[=34= 中插入第一行] 有 qty
的 5.
谢谢
老实说,我只想放弃使用“智能查询”的想法,而使用普通的编程循环。 “完成。” 准备 SELECT
和 INSERT
语句句柄,开始事务,运行 SELECT
。然后,INSERT
多次。最后,COMMIT
.
虽然毕竟可能有一种“聪明”的方法来做到这一点,但它可能不值得寻找。而且,它可能不会 显而易见, 这可能意味着很难按照要求继续前进 (不可避免地...) 改变。所以,我会说,“减少你的损失。”
我希望并想象一定有一个更高效的解决方案,但无论如何,请考虑以下几点:
架构 (MySQL v8.0)
DROP TABLE IF EXISTS product_batches;
CREATE TABLE product_batches
(batch_number SERIAL PRIMARY KEY
,product_id INT NOT NULL
,quantity_available INT NOT NULL
);
INSERT INTO product_batches VALUES
( 1,1,15),
( 3,1, 5),
( 7,1,20),
(10,1,30),
(11,1,50);
查询#1
SELECT batch_number
, product_id
FROM
( SELECT x.*
, COALESCE(LAG(SUM(y.quantity_available),1) OVER (ORDER BY batch_number),0) running
FROM product_batches x
JOIN product_batches y
ON y.product_id = x.product_id
AND y.batch_number <= x.batch_number
GROUP
BY x.batch_number
) a
WHERE running <=22;
batch_number | product_id |
---|---|
1 | 1 |
3 | 1 |
7 | 1 |
编辑:
没有广泛测试,但对于旧版本,我认为你可以这样做(虽然性能可能很糟糕),所以认真考虑升级:
SELECT x.*
, z.total - SUM(y.quantity_available) running
FROM product_batches x
JOIN product_batches y
ON y.product_id = x.product_id
AND y.batch_number >= x.batch_number
JOIN (SELECT product_id, SUM(quantity_available) total FROM product_batches GROUP BY product_id) z
ON z.product_id = x.product_id
GROUP
BY x.batch_number
HAVING running <= 22;
编辑 2:
也许这样更清楚:
SELECT x.*
, GREATEST(SUM(y.quantity_available)-22,0) balance
FROM product_batches x
JOIN product_batches y
ON y.product_id = x.product_id
AND y.batch_number <= x.batch_number
GROUP
BY x.batch_number
HAVING balance < quantity_available