INSERT INTO matched_articles
SELECT * FROM articles a LEFT JOIN info i ON a.id = i.article_id WHERE i.tag_id = 5;
INSERT INTO unmatched_articles
SELECT * FROM articles a WHERE a.id NOT IN (SELECT m.id FROM matched_articles m);
ここには多くの間違いがあり、どこから始めればよいのかわかりません。最初の挿入では、左結合は必要ありません。実際には、左結合はありません。そのはず
INSERT INTO matched_articles
SELECT * FROM articles a INNER JOIN info i ON a.id = i.article_id WHERE i.tag_id = 5;
もしあなたが左の参加を必要としていたなら、あなたは持っていただろう
INSERT INTO matched_articles
SELECT * FROM articles a LEFT JOIN info i ON a.id = i.article_id AND i.tag_id = 5;
左結合の右側からwhere句に何かを入れると(null値の検索以外)、その条件を満たす必要があるため、内部結合に変換します。したがって、右の表の一致は削除されます。
これで、2番目のステートメントは、左結合の特殊なケースで実行できますが、持っているものは機能します。
INSERT INTO matched_articles
SELECT * FROM articles a
LEFT JOIN info i ON a.id = i.article_id AND i.tag_id = 5
WHERE i.tag_id is null
これにより、articlesテーブルに一致するものを除いて、infoテーブルにあるすべてのレコードが得られます。
次に、挿入するフィールドを指定せずに挿入文を記述しないでください。また、特に結合がある場合は、select*を使用してselectステートメントを記述しないでください。これは一般的にずさんな、怠惰なコーディングであり、修正する必要があります。誰かが一方のテーブルの構造を変更したが、もう一方のテーブルの構造を変更しなかった場合はどうなりますか?この種のことはメンテナンスに不利であり、結合のあるselectステートメントの場合、列を2回返し(結合列)、サーバーとネットワークのリソースを浪費します。必要なものと必要なものだけを指定するのが面倒なのは、コーディングが不十分なだけです。したがって、習慣から抜け出し、本番コードに対して再度実行しないでください。
現在のスタメントが遅すぎる場合は、適切なインデックスで修正できる可能性もあります。idフィールドは両方のテーブルでインデックス付けされていますか?一方、数百万の記事がある場合は、挿入に時間がかかります。多くの場合、一度に50000のバッチでこれを行う方がよいでしょう(これに時間がかかりすぎる場合は、さらに少なくなります)。上位のXXXレコードを選択する挿入inaループを実行してから、影響を受ける行数がなくなるまでループします。