Mysql 使带有联接的更新应用于所有记录
我有三张桌子:Mysql 使带有联接的更新应用于所有记录,mysql,Mysql,我有三张桌子: TABLE bon TABLE order TABLE payed b_id | total | payed | diff id | b_id | amm id | b_id | amm -----+-------+-------+------ ---+------+----- ---+------+----- 1 | 0 | 0 | 0 1 |
TABLE bon TABLE order TABLE payed
b_id | total | payed | diff id | b_id | amm id | b_id | amm
-----+-------+-------+------ ---+------+----- ---+------+-----
1 | 0 | 0 | 0 1 | 1 | 5 1 | 2 | -10
-----+-------+-------+------ ---+------+----- ---+------+-----
2 | 0 | 0 | 0 2 | 2 | 5 2 | 3 | -5
-----+-------+-------+------ ---+------+----- ---+------+-----
3 | 0 | 0 | 0 3 | 1 | 15
---+------+-----
4 | 3 | 10
---+------+-----
5 | 2 | 15
---+------+-----
6 | 2 | 20
如果我只想更新一个id的bon总计,我会:
UPDATE `bon`
INNER JOIN (
SELECT
SUM(`amm`) AS `total`
FROM `order`
WHERE `b_id`=2
) AS s1
INNER JOIN (
SELECT
COALESCE(SUM(`amm`),0) AS `payed`
FROM `payed`
WHERE `b_id`=2
) AS s2
SET
`bon`.`total` = s1.`total`,
`bon`.`payed` = s2.`payed`,
`bon`.`diff` = s1.`total` + s2.`payed`
WHERE `b_id`=2;
将id 2正确更新为
b_id | total | payed | diff
-----+-------+-------+------
2 | 40 | -10 | 30
但是,我尝试使用以下内容更新所有id:
UPDATE `bon`
INNER JOIN (
SELECT
`b_id`,
SUM(`amm`) AS `total`
FROM `order`
) AS s1 ON bon.`b_id`=s1.`b_id`
INNER JOIN (
SELECT
`b_id`,
SUM(`amm`) AS `payed`
FROM `payed`
) AS s2 ON bon.`b_id`=s2.`b_id`
SET
`bon`.`total` = s1.`total`,
`bon`.`payed` = COALESCE(s2.`payed`,0),
`bon`.`diff` = s1.`total` + COALESCE(s2.`payed`,0)
遗憾的是,这不会更新任何行。那么我在这件事上错在哪里呢
编辑:我找到了一个解决方案,并将其发布在下面。我不知道这是否是最好的方法,但它有效。建议仍然受欢迎。虽然我还没有找到解决方案,但我认为您的第二个查询存在一些问题 1让我们看看您的第一个内部查询:
SELECT
`b_id`,
SUM(`amm`) AS `total`
FROM `order`
首先,这将从顺序中提取所有行,但是您的计算列(别名为total)在每一行中的值都相同
这可能不是你想要的。将该SELECT中的结果集与bon表连接并不意味着MySQL会在幕后应用一些魔法,并将连接中使用的列所产生的结果集分组
相反,首先生成表bon的叉积和第一个SELECT的结果集。该叉积在每行中的total值也相同。然后联接只过滤bin.b_id和s1.b_id相同的行
当然,这些行中的每一行仍然具有相同的总值,因此即使它进行了更新,也会得到错误的结果
补救办法是在SELECT语句中添加一个按b_id分组的语句。这将导致正确计算总数,即每个b_id。然后将使用分组的b_id进行连接
这同样适用于第二个SELECT内部查询
2您正在使用SELECT from表格payed进行内部联接。这意味着结果将不包含任何未在payed中的行。对于示例数据,结果将不包含b_id为1的行,因为付款表不包含此类行
这个问题不是那么容易解决的。一种解决方案是在运行查询之前确保payed表中有每个b_id。但是,当支付表中不存在的ID没有更新时,您可能会感到高兴
如果你能更详细地描述一下你想要什么,我们最终可以找到一个解决方案。我找到了一个解决方案,跳过了所有的连接。也许不是最好的答案,但它是有效的建议仍然是受欢迎的:
UPDATE `bon`
SET
`bon`.`total` =
(SELECT
COALESCE(SUM(`amm`),0)
FROM `order`
WHERE `order`.`b_id`=`bon`.`b_id`
),
`bon`.`payed` =
(SELECT
COALESCE(SUM(`amm`),0)
FROM `payed`
WHERE `payed`.`b_id`=`bon`.`b_id`
),
`bon`.`diff` =
(SELECT
COALESCE(SUM(`amm`),0)
FROM `order`
WHERE `order`.`b_id`=`bon`.`b_id`
)+
(SELECT
COALESCE(SUM(`amm`),0)
FROM `payed`
WHERE `payed`.`b_id`=`bon`.`b_id`
)
谢谢你的详细回答。我只想用其他两个表中相应值的总和来更新bon。对于每个b_id,总是至少有一个条目,但在payed中,它可能会丢失。我玩了各种各样的游戏,都没用。我找到了一个解决办法,放弃了所有的连接。我不知道这是否是最好的,但它确实有效。