2012-03-28 17 views
0

私は約4000個のバグに起因するエラーがある約7000行のテーブルを持っています。 (場所は'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 - You can't specify target table 't' for update in FROM clause

まあどのように私はその問題をsloveすることができます更新しながら、私は、行自体にアクセスすることができないようですか?

多分テンポラリテーブルを持っているかもしれませんが、少しオーバーヘッドのようですが、関連のないすべての行もコピーする必要があります。

私はまた、this answerで説明されているように、instatを使用しようとしましたが、選択した行を制限する必要があります。私は音がinteresstingた

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'; 
+0

なぜ、ストレートフォワードジョインの代わりにビューを使用していますか? – nnichols

+0

ジョインでの試行がうまくいかなかった。私のTriestの作業ソリューションは上記です。 – rekire

+0

最大値を得るために左結合を使用して私のソリューションを試しましたか?それはあなたのバージョンと同じ結果をビューと共に生成するはずですか? – nnichols

答えて

0

私はそれほど多くのことは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'; 

それが動作するかどうか私に教えて:)

+0

あなたの答えをありがとう。しかし、テストしなければ、これはうまくいかないでしょう。テーブル 't'はビューの定義では分かりません。しかし、私はその条件に "参加"することができるかもしれません... brb – rekire

+0

はい、条件にtl.end_ts = t.end_tsは表示されていてはいけません。選択結果を表示します。これを試して –

+0

: は、ビューtimelogView (timelogのTL FROM SELECT場所 ) UPDATE 'timelog'トン SET' location' =(!場所= 'NULL' timelogViewから位置 を選択)TL トンを作成します.end_ts> '2012-01-01 00:00:00' AND tl.end_ts = t.end_ts AND t.location = 'null'; –

2

ソリューション:私は一時ビューで自分自身のソリューションをしようとした回答に基づいて


。多分あなたはそれを試してみるでしょうか?

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'; 

そのような何か?

+0

質問をする前に、このページを華麗に開いています。私は私の場合にこれをどのように使うべきか分かりません。 – rekire

+0

見た目は変わっても動作しません:*#1064 - SQL構文にエラーがあります。あなたのMySQLサーバーのバージョンに対応するマニュアルをチェックして、正しい構文が近くで使用できるようにしてください。 '' 10行目* – rekire

+0

私はあなたの答えをアップアップしました。 – rekire

1

あなたは以下を使用することができるはず -追加LEFTは、その時刻t2から最新の値で更新を強制するために、JOIN

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結合基準に一致します(ID DESC LIMIT 1の順序と同じ効果)。

+0

log_idは私の主キーであり、 'NULL'にすることはできません。主要な部分が機能する可能性があります。 – rekire

+0

この場合、LEFT JOIN ... IS NULLの考え方は、より高いIDと一致しないレコードを見つけることです。したがって、 't3.log_id IS NULL' – nnichols