ど素人から毛を生やす。<延>

[MySQL]該当レコード群の最新○件のみをUPDATE(JOIN編)

Web > Other 2023年9月28日(最終更新:6月前)

どもです。
MySQLではUPDATE句でもORDER BYやLIMITを使用できるため、条件に合う最新○件のレコードを更新、という処理が可能です。

が、UPDATEにJOINを使用すると、Incorrect usage of UPDATE and ORDER BY エラーになってしまいます。
ORDER BYだけでなくLIMITも使用できません。

TABLE_ATABLE_B
id(int)id(int)
text(TEXT)
date(DATE)

TABLE_B.dateが指定より古いレコードのTABLE_A.textを更新する場合、どうすればここにORDER BYやLIMITを適用できるでしょうか。

TABLE_ATABLE_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_ATABLE_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を使用する工夫が必要です。

この記事は役に立ちましたか?
  • _(:3」∠)_ 面白かった (0)
  • (・∀・) 参考になった (0)
  • (`・ω・´) 役に立った (0)