web-dev-qa-db-ja.com

左結合を使用したMySQL更新クエリ

テーブルスキーマ

テーブル名:file_manager_folder

行:idparentIdname

私のクエリは、フォルダーを別のフォルダーに移動することをシミュレートし、IN(?)を使用して配列を受け入れます。

同じparentIdと名前のフォルダーがまだない場合にのみ、フォルダーを「移動」するように更新する必要があります。通常のファイルシステムで予想される動作の種類。

たとえば、次のとおりです。

UPDATE file_manager_folder set parentId = 54 where id IN( '1','2',3') 

ParentIdと名前については何もチェックしないクエリになります...しかし、どうすれば左結合を機能させることができますか。

ここに私が試したものがあります。

SELECT * FROM 
    file_manager_folders as a
LEFT JOIN file_manager_folders as b on a.id = b.id 
WHERE b.id IS NOT NULL and a.id IN("1","2","3") and a.parentId = 54

UPDATE table1 LEFT JOIN table2 SET t1.x = t2.y ON condition WHERE conditions

24
Layke

したがって、ターゲットの親フォルダーの下に同じ名前のフォルダーが存在する場合にのみフォルダーを移動する必要がありますnot

UPDATE file_manager_folder f1
LEFT OUTER JOIN file_manager_folder f2 
    ON f1.name = f2.name AND f2.parentId = 54
SET f1.parentId = 54 
WHERE f2.name IS NULL AND f1.id IN (1,2,3);

結合条件は、ターゲットの親の下で同じ名前のフォルダーを検索します。 WHERE句は、そのようなフォルダーが存在しないことをテストします(外部結合で一致が見つからない場合のみ、f2.nameはnullです)。

51
Bill Karwin

これは、parentid列とname列で 一意の制約/インデックス を使用して解決する必要があると思います。それ以外の場合、テーブルへのINSERT/UPDATEアクセス権を持つユーザーは、ビジネスルールを回避できます。

CREATE UNIQUE INDEX blah_uk ON FILE_MANAGER_FOLDER(parentId, name) USING BTREE
2
OMG Ponies

素朴ですが、これはどうですか?

UPDATE file_manager_folder SET parentId = 54 
WHERE id IN( '1','2','3') 
AND parentId != 54 
AND name NOT IN (SELECT name FROM file_manager_folder WHERE id IN ('1', '2', '3'))
2
eyescream

NOT INの代わりにLEFT joinを使用すると、パフォーマンスが低下します。

クエリを実行する前にExplainを実行すると、問題は明らかです。

0
Sunil