2014-01-25 5 views
1

Почему этот запрос:Штанге SQL UPDATE из SELECT,

UPDATE 
    (SELECT A.id trophy_id 
    FROM usertrophys A, 
     userinfo B 
    WHERE A.user_id = B.id 
    AND B.cidade_new_id = 25755 
    AND ban = 0 
    AND A.platform = 'vita' 
    ORDER BY points DESC, platinum DESC, gold DESC, silver DESC, bronze DESC, total DESC)  A 
LEFT JOIN rankgeralcidade B USING (trophy_id) 
SET B.rank = @r:= (@r+1) 
WHERE platform = 'vita' 
    AND meninas = 0 
    AND cidade_id = '25755' 
    AND trophy_id = B.trophy_id;</code></pre> 

заканчивается этим результатом

select * from rankgeralcidade where cidade_id = 25755 and platform = 'vita' ; 
+--------+-----------+----------+---------+------+-----------+-----------+---------------------+---------+---------------------+-----------+ 
| id  | trophy_id | platform | user_id | rank | last_rank | best_rank | best_rank_date  | meninas | date_updated  | cidade_id | 
+--------+-----------+----------+---------+------+-----------+-----------+---------------------+---------+---------------------+-----------+ 
| 138300 |  86412 | vita  | 2774 | 1 |   1 |   1 | 2013-02-09 18:07:25 |  0 | 2012-12-25 05:20:30 |  25755 | 
| 182075 | 120401 | vita  | 3546 | 2 |   0 |   0 | 2014-01-25 19:04:55 |  0 | 2014-01-25 19:04:55 |  25755 | 
+--------+-----------+----------+---------+------+-----------+-----------+---------------------+---------+---------------------+-----------+ 
2 rows in set (0.00 sec) 

когда следующий выбор есть это возвращение

mysql> SELECT @r:= (@r+1), B.* 
FROM 
    (SELECT A.id trophy_id 
    FROM usertrophys A, 
     userinfo B 
    WHERE A.user_id = B.id 
    AND B.cidade_new_id = 25755 
    AND ban = 0 
    AND A.platform = 'vita' 
    ORDER BY points DESC, platinum DESC, gold DESC, silver DESC, bronze DESC, total DESC) A 
LEFT JOIN rankgeralcidade B USING (trophy_id); 
+-------------+--------+-----------+----------+---------+------+-----------+-----------+---------------------+---------+---------------------+-----------+ 
| @r:= (@r+1) | id  | trophy_id | platform | user_id | rank | last_rank | best_rank | best_rank_date  | meninas | date_updated  | cidade_id | 
+-------------+--------+-----------+----------+---------+------+-----------+-----------+---------------------+---------+---------------------+-----------+ 
|   1 | 182075 | 120401 | vita  | 3546 | 2 |   0 |   0 | 2014-01-25 19:04:55 |  0 | 2014-01-25 19:04:55 |  25755 | 
|   2 | 138300 |  86412 | vita  | 2774 | 1 |   1 |   1 | 2013-02-09 18:07:25 |  0 | 2012-12-25 05:20:30 |  25755 | 
+-------------+--------+-----------+----------+---------+------+-----------+-----------+---------------------+---------+---------------------+-----------+ 
2 rows in set (0.01 sec)

Основная проблема, почему ид = "182075" из rankgeralcidade обновляется с рангом = 2? в том же запросе, просто заменив UPDATE на SELECT, результаты кажутся прекрасными.

ответ

1

Вот select запрос:

SELECT @r:= (@r+1) as rank, B.* 
FROM (SELECT A.id trophy_id 
     FROM usertrophys A join 
      userinfo B 
      on A.user_id = B.id 
    WHERE B.cidade_new_id = 25755 AND ban = 0 AND A.platform = 'vita' 
    ORDER BY points DESC, platinum DESC, gold DESC, silver DESC, bronze DESC, total DESC 
    ) A LEFT JOIN 
    rankgeralcidade B 
    USING (trophy_id); 

Внешний запрос не имеет order by положение. Это означает, что порядок результатов не определен. Не имеет значения, что в подзапросе есть предложение order by. Even, если заказ был сохранен (что не гарантируется), join может привести к тому, что данные будут упорядочены по-другому.

То, что a update и select будет производить разные заказы, имеет для меня прекрасный смысл.

Если вы хотите стабильное присвоение значений, то используйте order by предложения по самым дальним запросам, как для select, так и для order by.

EDIT:

Я не понимаю, что MySQL не поддерживает order by с join (потому что я не использую order by на обновления очень много). Вы все еще можете сделать это с помощью подзапроса:

update rankgeralcidade b join 
     (<the select query here> 
     ) toupdate 
     on b.trophy_id = toupdate.trophy_id 
    set B.rank = toupdate.rank; 
+0

Почему вы выполняете левое внешнее соединение, а затем выбираете только строки из второй таблицы? Если совпадения нет, тогда они будут «NULL». –

+0

добавление ORDER BY вызывает «Неправильное использование UPDATE и ORDER BY» – fabriciols