2015-09-08 43 views
3

我有兩個表,一個帶有參與者及其排名,另一個帶有優惠券代碼及其排名。我想爲每位參與者分配正確等級的優惠券代碼,但確保每張優惠券代碼僅使用一次,當然。MySQL在更新查詢中僅分配匹配一次

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

要確保憑證只有在您可以向'A.voucherid'添加'UNIQUE KEY'時纔會使用,但是您將無法使用該查詢更新所有行,因爲它會嘗試插入重複項,整個更新將失敗 –

回答

0

我想我使用user variables找到答案,這就是爲什麼我回答我自己的問題。

這個想法是使用一個計數器作爲第二個比較變量,以確保具有rank1的憑證1被分配給一個參與者,並且具有rank1的憑證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)之前執行,這會導致錯誤的結果。