MySQL 分配在更新查询中仅匹配一次
Posted
技术标签:
【中文标题】MySQL 分配在更新查询中仅匹配一次【英文标题】:MySQL Assign matches only once in an update query 【发布时间】:2015-12-04 08:01:29 【问题描述】:我有两张表,一张包含参与者及其排名,另一张包含优惠券代码及其排名。我想为每个参与者分配一个具有正确等级的优惠券代码,但当然要确保每个优惠券代码只使用一次。
Table A: Table B:
pid | name | rank | voucherid voucherid | rank | code | used
1 | Max | 10 | null 1 | 10 | AAA | 0
2 | Joe | 20 | null 2 | 10 | BBB | 0
3 | Eva | 10 | null 3 | 20 | CCC | 0
4 | 20 | DDD | 0
我正在寻找产生此结果的更新查询:
Table A:
pid | name | rank | voucherid
1 | Max | 10 | 1
2 | Joe | 20 | 3
3 | Eva | 10 | 2
以下方法不起作用,因为它将同一张凭证分配给多个参与者:
UPDATE A
JOIN B ON A.`rank` = B.`rank`
SET A.`voucherid` = B.`voucherid`
WHERE
A.`voucherid` IS NULL AND
B.`used` = 0
;
-
Result:
Table A:
pid | name | rank | voucherid
1 | Max | 10 | 1
2 | Joe | 20 | 3
3 | Eva | 10 | 1 !!!
之后我当然会更新凭证表 B 将used
列设置为1
。
【问题讨论】:
为了确保凭证仅在您可以将UNIQUE KEY
添加到A.voucherid
时使用,但您将无法使用该查询更新所有行,因为它会尝试插入重复,整个更新将失败
【参考方案1】:
我想我使用user variables
找到了答案,这就是我回答自己问题的原因。
这个想法是使用一个计数器作为第二个比较变量,以确保将等级为 1 的凭证 1 分配给一个参与者,将等级 1 的凭证 2 分配给另一个参与者。
mysql 查询相当繁琐。这就是为什么我可能使用 php 来解决问题。但至少我想分享它:
UPDATE `A` AS ua
JOIN (
SELECT
ta.`participantid`, ta.`rank`,
(@ca := IF(@pa = ta.`rank`, @ca + 1, 0)) AS `counter`,
@pa := ta.`rank`
FROM `A` AS ta, (SELECT @ca := 0, @pa := 0) AS ia
WHERE
ta.`voucherid` IS NULL
ORDER BY `rank` ASC
) AS a ON a.`pid` = ua.`pid`
JOIN (
SELECT
tb.`voucherid`, tb.`rank`,
(@cb := IF(@pb = tb.`rank`, @cb + 1, 0)) AS `counter`,
@pb := tb.`rank`
FROM `B` AS tb, (SELECT @cb := 0, @pb := 0) AS ib
WHERE
tb.`used` = 0
ORDER BY `rank` ASC
) AS b ON (b.`rank` = a.`rank` AND b.`counter` = a.`counter`)
JOIN `B` AS ub ON ub.`voucherid` = b.`voucherid`
SET
ua.`voucherid` = b.`voucherid`,
ub.`used` = 1
;
它在我准备的测试用例中有效,但根据MySQL documentation,您不能依赖表达式的评估顺序。因此@pa := ta.rank
可能会在IF(@pa = ta.rank)
之前执行,这会导致错误的结果。
【讨论】:
以上是关于MySQL 分配在更新查询中仅匹配一次的主要内容,如果未能解决你的问题,请参考以下文章
仅从日期时间字段(mysql)中提取日期并将其分配给 php 变量