SQLの内部結合の方法

タイムランの絞り込み機能を実装する際に、キーワード検索と同時に行うと実行できないという不具合が発生するということがわかりました。この原因を確かめていたところ、キーワード検索を担う部分と、今回自分が追加した部分が違う方法でテーブルの結合を行っていることがわかりました。

以前はdisplayParamの変更に合わせて然るべきテーブルがFROMの後に加えられるようにしていました。その文が以下の通りです。

   body.append(" FROM eip_t_timeline");
    if ("L".equals(displayParam)) {
      body.append(", eip_t_timeline_url");
    } else if ("FILE".equals(displayParam)) {
      body.append(", eip_t_timeline_file");
    }

しかしキーワード検索を担う部分は以下のような処理を行っていました。

    if ((keywordParam != null) && (!keywordParam.equals(""))) {
      hasKeyword = true;
      body.append(" LEFT JOIN eip_t_timeline AS comment ");
      body.append(" ON eip_t_timeline.timeline_id = comment.parent_id ");
    }

つまり、もしタイムラインの絞り込みとキーワード検索を同時に行った場合、以下のようなSQLの命令が出されることになります。

FROM eip_t_timeline, eip_t_timeline_url LEFT JOIN eip_t_timeline AS comment ON eip_t_timeline.timeline_id = comment.parent_id 

これでは結合の方法がバラバラであるため、上手く命令出来ていないということがわかりました。 そこで結合の方法をJOINを記述する方法に統一しました。 3つ以上のテーブルをJOINで結合する際の書き方は http://pgcafe.moo.jp/SQL/main_2.htm を参考にしました。 そして書き換えた後の文は以下の通りです。

   body.append(" FROM ");
    if ("L".equals(displayParam) || "FILE".equals(displayParam)) {
      body.append("(");
    }
    body.append(" eip_t_timeline ");
    if ("L".equals(displayParam)) {
      body.append(" JOIN eip_t_timeline_url AS url ");
      body.append(" ON eip_t_timeline.timeline_id = url.timeline_id ) ");
    } else if ("FILE".equals(displayParam)) {
      body.append(" JOIN eip_t_timeline_file AS file ");
      body.append(" ON eip_t_timeline.timeline_id = file.timeline_id ) ");
    }

こうすることにより、タイムラインの絞り込みとキーワード検索を同時に行った場合のSQLへの命令は以下のようになります。

FROM ( eip_t_timeline  JOIN eip_t_timeline_url AS url  ON eip_t_timeline.timeline_id = url.timeline_id )  LEFT JOIN eip_t_timeline AS comment ON eip_t_timeline.timeline_id = comment.parent_id 

これで正しく命令されるようになりました。