Xpoint
   [напомнить пароль]

обновить таблицу с помощью нее самой

Метки: [без меток]
2006-10-12 23:48:25 [обр] firestorm[досье]

Уважаемые!

Есть таблица, в ней поля Field1 и Field.
Нужен запрос, по смыслу такой:
update table as t1 SET field1=(select field1+field2 from table as t2 where t2.id+1=t1.id)
Все столбцы field2 заполнены.

Т.е каждое следующее значение field1 это сумма полей field1+field2 для предыдущей строчки.
Есть решения?

спустя 2 часа [обр] Давид Мзареулян(3/1003)[досье]
Скорее всего, на чистом SQL этого не сделать. Но в любом случае следует вначале определить понятие «предыдущей строчки».
спустя 1 час 5 минут [обр] firestorm[досье]
Конечно, в таблице есть поле id - unique, auto_increment
Соответственно предыдущая (при id>1) это та, у которой t2.id=t1.id-1, т.е значение id различаются на 1
спустя 3 минуты [обр] Давид Мзареулян(3/1003)[досье]
Скажем, это можэно сделать в PostgreSQL: там есть конструкция update … from …. Но в стандарте SQL этого нет.
спустя 7 часов [обр] firestorm[досье]

А в MYSQL можно?

Такой запрос как я привел вначале работал БЫ, если бы обновлялась ДРУГАЯ таблица, а выбиралось из первой...

спустя 14 часов [обр] Закиров Руслан(12/343)[досье]

Это ограничение MySQL - нельзя в подзапросе использовать таблицу, которую вы изменяете. Читаем http://bugs.mysql.com/bug.php?id=5037 и дальше по ссылке мануал.

Можно использовать временную таблицу и это будет самое правильное решение. Копируем таблицу во временную, проводим обновление и дропаем ее.

Можно для одноразового использования применить:

UPDATE test_update t1, test_update t2 SET t1.field = t1.field + t2.field WHERE t1.id = t2.id+1;

Но этот запрос может дать неверные результаты так как порядок обновления не контролируется, например по каким-то причинам mysql решит обновить запись с id = 3 раньше записи с идентификатором 2.

Если записи были удалены, то тоже будут проблемы, например нет записи с id = 2, но есть 3. Это ограничение можно обойти:

UPDATE
  test_update t1,
  test_update t2
  LEFT JOIN test_update t3 ON (t3.id > t2.id AND t3.id < t1.id )
SET t1.field = t1.field + t2.field
WHERE t2.id < t1.id AND t3.id IS NULL;

Пример правильной работы:

mysql> select * from test_update order by id;
+------+-------+
| id   | field |
+------+-------+
|    1 |     1 |
|    3 |     3 |
|    5 |     5 |
+------+-------+
mysql> UPDATE test_update t1, test_update t2 LEFT JOIN test_update t3...
mysql> select * from test_update order by id;
+------+-------+
| id   | field |
+------+-------+
|    1 |     1 |
|    3 |     4 |
|    5 |     9 |
+------+-------+

И неправильной(из-за порядка обновления):

mysql> delete from test_update;
mysql> insert into test_update values(5,5), (3,3), (1,1);
mysql> UPDATE ...;
mysql> select * from test_update order by id;
+------+-------+
| id   | field |
+------+-------+
|    1 |     1 |
|    3 |     4 |
|    5 |     8 |
+------+-------+

Так что решать вам.

Powered by POEM™ Engine Copyright © 2002-2005