どもです。
MySQLではUPDATE句でもORDER BYやLIMITを使用できるため、条件に合う最新○件のレコードを更新、という処理が可能です。
が、UPDATEにJOINを使用すると、Incorrect usage of UPDATE and ORDER BY エラーになってしまいます。
ORDER BYだけでなくLIMITも使用できません。
TABLE_A | TABLE_B |
---|---|
id(int) | id(int) |
text(TEXT) | |
date(DATE) |
TABLE_B.dateが指定より古いレコードのTABLE_A.textを更新する場合、どうすればここにORDER BYやLIMITを適用できるでしょうか。
TABLE_A | TABLE_B |
---|---|
id(int) | id(int) |
text(TEXT) | |
date(DATE) | |
is_UPDATE(TINYINT) |
TABLE_Bのテーブル定義を変更できるのであれば、更新フラグを設置すれば手っ取り早く解決できます。
TABLE_B単品であればORDER BYやLIMITが使用できるため、
UPDATE TABLE_B SET is_UPDATE = 1 WHERE TABLE_B.date < ○○ ORDER BY TABLE_B.date ASC LIMIT 500;
UPDATE TABLE_B AS tb INNER JOIN TABLE_A AS ta ON tb.id = ta.id SET ta.text = ☆☆ WHERE TABLE_B.is_UPDATE = 1;
①TABLE_Bのみを対象に、ORDER BYやLIMITで更新対象フラグを立てる。
②TABLE_A・TABLE_BをJOINし、更新対象フラグを条件にUPDATEする。
これなら②のUPDATEではORDER BYやLIMITを使用せずに済みます。
また、TABLE_A側に更新の条件がある場合は、TABLE_Bのフラグ列を2つに増やし、
TABLE_A | TABLE_B |
---|---|
id(int) | id(int) |
text(TEXT) | |
date(DATE) | |
is_satisfy(TINYINT) | |
is_UPDATE(TINYINT) |
UPDATE TABLE_B AS tb INNER JOIN TABLE_A AS ta ON tb.id = ta.id SET tb.is_satisfy = 1 WHERE TABLE_A.×× = ▽▽;
UPDATE TABLE_B SET is_UPDATE = 1 WHERE TABLE_B.date < ○○ AND TABLE_B.is_satisfy = 1 ORDER BY TABLE_B.date ASC LIMIT 500;
UPDATE TABLE_B AS tb INNER JOIN TABLE_A AS ta ON tb.id = ta.id SET ta.text = ☆☆ WHERE TABLE_B.is_UPDATE = 1;
①TABLE_A・TABLE_BをJOINし、ORDER BYやLIMITは無視して要件を満たすフラグを立てる。
②TABLE_Bの要件を満たすフラグを立てたレコードのみを対象に、ORDER BYやLIMITを使用し更新フラグを立てる。
③TABLE_A・TABLE_BをJOINし、更新フラグを元にTABLE_Aを更新。
これで更新できました。
JOINしたUPDATEではORDER BYやLIMITを使用できないので、SQLの発行を分割し、JOINなしでORDER BYやLIMITを使用する工夫が必要です。