CREATE TEMPORARY TABLE と mybatis

一時テーブルを使用して以下のように集計を行うこと

DROP TABLE IF EXISTS tempdays;
CREATE TEMPORARY TABLE tempdays
SELECT * FROM ( SELECT CURDATE() AS 't_date'
UNION ALL SELECT ADDDATE(CURDATE(), -1) AS 't_date'
UNION ALL SELECT ADDDATE(CURDATE(), -2) AS 't_date'
UNION ALL SELECT ADDDATE(CURDATE(), -3) AS 't_date'
) x;

SELECT t.t_date , COUNT(a.id)
FROM tempdays t LEFT JOIN access a
ON t.t_date = a.connect_date
GROUP BY t.t_date;

このような例はよく使われる形である。
これらステップを踏んだ SELECT結果を mybatis で取得するのに、
1つのSQLMap の statement では無理である。

DROP TABLE IF EXISTS の実行と、CREATE TEMPORARY TABLの実行、
SELECT の実行に分けるしかない。
同じSqlSession で行う必要がある。



SQLMap は以下のように記述して

<update id="droptemp">

   DROP TABLE IF EXISTS tempdays
</update>

<update id="createtemp" parameterType="test.PdayParameter">

   CREATE TEMPORARY TABLE tempdays
   SELECT * FROM ( SELECT CURDATE() 't_date'
   <foreach item="item" open="" close="" collection="predayList" separator=" ">
   UNION ALL SELECT ADDDATE(CURDATE(), #{item} ) 't_date'
   </foreach>
   ) x
</update>

<select id="testaccess" resultType="test.entity.AccessData">

   SELECT t.t_date    AS adate
         ,COUNT(a.id) AS acount
   FROM tempdays t LEFT JOIN access a
   ON t.t_date = a.connect_date
   GROUP BY t.t_date
</select>

org.apache.ibatis.session.SqlSession の実行を
この順番で実行すればよい。
id="createtemp" の foreach に渡すパラメータは、parameterType="test.PdayParameter" が、
predayList という Java Collection のパラメータをupdate id="createtemp" の
パラメータである PdayParameter が持つことであり、以下のように用意する。

package test;
import java.util.ArrayList;
import java.util.List;
public class PdayParameter{
   public List<Integer> predayList;

   public PdayParameter(){
      predayList = new ArrayList<Integer>();
   }

   public void add(int i){
      predayList.add(i);
   }
}
=====
実行するところは、、、

getSqlSession().update("droptemp");

PdayParameter pdayParameter = new PdayParameter();
for(int i = -1; i >= -20 ; i-- ){
   pdayParameter.add(i);
}

getSqlSession().update("createtemp", pdayParameter);

List<AccessData> list = getSqlSession().selectList(bindId(SelectMapper.class, "testaccess"));

しかし、こんなことするより、ストアドプロシジャを用意して mybatis の
CALLABLE を呼んだ方が良いのかもしれない。