- MT6.03で確認
例えば、
まだ1件もアイテムを関連付けていない記事を取り出す
ようなケースでは外部結合を使います。
外部結合は、複数のテーブルから一致する要素の有無にかかわらず結合して表示します
参考 第6回 SQL基礎II|OSS-DB入門|OSS-DB道場|受験対策|DBスペシャリストを認定する資格 OSS-DB技術者認定試験
なので、アイテムの関連付けの有無に係らず結合しておき、そこから関連付けのないものだけ抽出すればよいわけですね。
SQLにするとこんな感じでしょうか。
SELECT e.entry_id, e.entry_title FROM mt_entry e LEFT OUTER JOIN mt_objectasset oa ON oa.objectasset_object_ds = 'entry' AND e.entry_id = oa.objectasset_object_id WHERE e.entry_class = 'entry' AND oa.objectasset_object_id IS NULL;
これは、アイテムの関連付けのほかにも、コメント、ロール割り当てなどいろいろ使えます。
で、これを MT::Object
でSQLを無理やりexecuteする以外で行う方法がわかりませんでした。
調べてみると
危うく「MT::Object、OUTER JOINとかできねーのかよf○○k」とかよく調べもせずに呟くところでした MT/ObjectDriver/Driver/DBI.pm読んだらできました でもドキュメント欲しかったです #movabletype
— Yuichi Takeuchi (@takeyuweb) 2014, 6月 17
lib/MT/ObjectDrivcer/Driver/DBI.pm の、prepare_statement のあたりに書いてあるので、詳しくはそちらを読めばよいです。
https://github.com/movabletype/movabletype/blob/mt6.0.3/lib/MT/ObjectDriver/Driver/DBI.pm
サンプルコード
my @entries = MT->model( 'entry' )->load( undef, { 'join' => MT->model( 'objectasset' )->join_on( undef, { object_id => \' IS NULL', }, { type => 'LEFT OUTER', condition => { object_ds => 'entry', object_id => \' = entry_id', }, }, ), } );
join_on
と \' IS NULL'
のあたりについては、@okayamaさんのちょっとイレギュラーな join 指定でオブジェクトを load するという記事に詳しく説明があるので、そちらをお読み頂くとして、外部結合を行うためには、以下を指定します。
join_on
の第三引数でtype
で結合の種類(ここではLEFT OUTER
)を指定condition
でON句(結合の条件)
このことは、こちらの657行目あたりから書いてありますので確認してみてください。
要はtype
を渡したときは、condition
の内容とあわせて、JOIN句を組み立ててくれるという感じです。
あとはWHERE句のobjectasset_object_id IS NULL
が組み立てられるように第二引数で指定すればOKです。