Обновить строку с собственной ссылкой в ​​подзапросе - PullRequest
0 голосов
/ 28 марта 2012

У меня есть таблица с около 7000 строк, где около 4000 имеют ошибку, вызванную ошибкой.(Местоположение 'null' , а не NULL и должно быть чем-то другим.) Теперь я пытаюсь исправить данные, которые доступны практически для всех строк.

UPDATE `timelog` t
SET `location`=(SELECT location
                FROM timelog tl
                WHERE tl.end_ts=t.end_ts AND location != 'null'
                ORDER BY tl.log_id DESC
                LIMIT 0,1) -- Just to make sure that I get 1 or 0 results
WHERE end_ts > '2012-01-01 00:00:00' AND location = 'null';

Но я получаю ошибку:

# 1093 - Вы не можете указать целевую таблицу 't' для обновления в предложении FROM

Что ж, похоже, я не могу получить доступ ксама строка при обновлении, как я могу решить эту проблему?

Может быть, с временной таблицей, но это, кажется, немного накладные расходы, и мне приходится копировать все несвязанные строки тоже.

Iтакже пытался использовать instat объединение, как описано в этом ответе , но мне нужно ограничить выбранную строку.


На основе ответов я попробовал свое собственное решение с временным представлением:

CREATE OR REPLACE VIEW right_locations AS
SELECT l.*, t.end_ts, t.location, (SELECT location FROM timelog tl WHERE tl.end_ts=t.end_ts AND location != 'null' ORDER BY tl.log_id DESC LIMIT 0,1) AS "possible", t.end_location
FROM `log` l
JOIN timelog t ON t.log_id=l.log_id
WHERE l.action_id =7 AND l.ts > '2012-01-01 00:00:00'
ORDER BY end_location;

UPDATE timelog t
JOIN right_locations r ON r.log_id=t.log_id
SET t.location = r.possible
WHERE t.end_ts > '2012-01-01 00:00:00' AND t.location = 'null';

Ответы [ 3 ]

2 голосов
/ 28 марта 2012

решение, которое я нашел, звучит интересно.Может быть, вы попробуете?

http://www.xaprb.com/blog/2006/06/23/how-to-select-from-an-update-target-in-mysql/

UPDATE timelog t
SET location = (
  select location from (
    SELECT tl.location
    FROM timelog tl
    WHERE tl.end_ts = t.end_ts AND tl.location != 'null'
    ORDER BY tl.log_id DESC
    LIMIT 1
 ) as x
WHERE 
  t.end_ts > '2012-01-01 00:00:00' AND 
  t.location = 'null';

что-то подобное?

1 голос
/ 28 марта 2012

Вы должны иметь возможность использовать следующее -

UPDATE timelog t1
INNER JOIN timelog t2
    ON t1.end_ts = t2.end_ts
    AND t2.location != 'null'
LEFT JOIN timelog t3
    ON t2.end_ts = t3.end_ts
    AND t3.location != 'null'
    AND t2.log_id < t3.log_id
SET t1.location = t2.location
WHERE t1.end_ts > '2012-01-01 00:00:00'
AND t1.location = 'null'
AND t3.log_id IS NULL;

EDIT Добавлено LEFT JOIN для принудительного обновления с последним значением из t2, которое соответствует критериям соединения (тот же эффект, что и порядокID DESC LIMIT 1).

0 голосов
/ 28 марта 2012

Я не так много работаю с MySQL, но вы можете попытаться создать представление с подзапросом, а затем использовать это представление.

create view timelogView
(
SELECT location
FROM timelog tl
WHERE tl.end_ts=t.end_ts AND location != 'null'
ORDER BY tl.log_id DESC
LIMIT 0,1
)

UPDATE `timelog` t
SET `location`=(SELECT location
                FROM timelogView tl) -- Just to make sure that I get 1 or 0 results
WHERE end_ts > '2012-01-01 00:00:00' AND location = 'null';

, дайте мне знать, если это работает:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...