我有两张桌子,一张是参与者和他们的排名,另一张是凭证代码及其排名。我想为每个参与者分配一个具有正确排名的优惠券代码,但当然要确保每个优惠券代码只使用一次。
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
。
答案 0 :(得分:0)
我认为我使用user variables
找到了答案,这就是我回答自己问题的原因。
这个想法是使用一个计数器作为第二个比较变量,以确保将具有rank1的voucher1分配给一个参与者,并将具有rank1的voucher2分配给另一个参与者。
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)
之前执行,这会导致错误的结果。