スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

CakePHPで最大値を含むレコードを高速に取得

  • 2012/03/21 16:01
  • Category: CakePHP
例えばid, name, dateというテーブルがあるとする。nameごとに最大のdateのidを抜きたい。が、普通にMAX(date)としても、idは必ずしもそのdateがあるレコードのものが得られない。なので普通は内部連結とか用いるけどCakePHPは原則そのへん禁止。この例だと、いったんname+最大dateのテーブル(Bと呼ぶ)を作って、最初のテーブル(Aと呼ぶ)のnameとdateがBにあるか探して、Bのidをとってくればよさそう。だけどCakePHPではINをダブルで発行する方法がよくわからない。queryで(name, date) IN 何々と書こうとしたけど、何々を何と書けばいいか詰まった。それにINNER JOINで試しに当ててみようとSQL書いてphpMyAdminで発行したらわずか2万行弱のテーブルで数分かかった。こりゃだめだ。
なので、お得意のCONCATを使うことにした。


// 最大値を取得しつつnameとdateの連結フィールドを作ってリスト化(つまり「HOGEHOGE2012-01-01 00:00:00」とか。良い例ではない)
// ちなみにfind('list')だとCONCATの結果が取れないようなのでわざわざallで取って整形している
$l1 = $this->Hoge->find('all', array('fields'=>array('Hoge.id', 'CONCAT(Hoge.name, MAX(Hoge.date)) AS id_date'), 'group'=>'Hoge.name'));
$l2 = set::combine($l1, '{n}.Hoge.id', '{n}.0.id_date');

// 当初のテーブルも連結フィールドを作って両者接続!
$conditions['CONCAT(Hoge.name,Hoge.date) AS id_date'] = array_values($l2);
$l3 = $this->Hoge->find('all', array('conditions'=>$conditions));

もちろんMySQL限定でのお話なのでご了承ください。それにしてもMAXで引いた値がある列を最初からとってくれればこんな苦労しないで済むのにね。

Pagination

Trackback

Trackback URL

http://muurimemo.blog.fc2.com/tb.php/11-ded4c4ce

Comment

Post Your Comment

コメント:登録フォーム
公開設定

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。