トップ > Tech > PHP > CakePHP > find で集計関数(count, sum など)を利用した list を取得する

find で集計関数(count, sum など)を利用した list を取得する

find を 'list' で呼び出すと primaryKey と displayField の対が得られる。 この組み合わせを変えるには、find の第2引数の fields にフィールドのリストを渡せばいい。

だが、group を併用してグループ化したデータに対して集計関数 count, sum などを使用した場合、 リスト化がうまくいかなかったので、メモ。

まず、下記のようなコードを書いた。

$data = $this->Tag->find('list', 
  array(
    "fields" => array("Tag.tag", "COUNT(Tag.tag) AS `tag`"),
    "group" => array("Tag.tag"),
  )
); 

これを実行して、こんな↓感じでデータがほしいわけだが、これがうまくいかず、値が null になる。

Array(
  [a] => 3,
  [b] => 12,
  [c] => 8,
)

で、試しに普通に find してみた。

$data = $this->Tag->find('all', 
  array(
    "fields" => array("Tag.name", "COUNT(Tag.name) AS `count`")
    "group" => array("Tag.tag"),
  )
); 

するとデータはこんな感じになるらしい。

Array(
  [0] => Array(
    [Tag] => Array( [name] => a ),
    [0] => Array( [count] => 3 ),
  ),
  [1] => Array(
    [Tag] => Array( [name] => b ),
    [0] => Array( [count] => 12 ),
  ),
  [2] => Array(
    [Tag] => Array( [name] => c ),
    [0] => Array( [count] => 8 ),
  ),
)

なんじゃこりゃ。なんとも面倒な形だ。というわけで Set::Combine を用いて、希望の形にする。 count のほうの添え字が 0 という番号だが、Set::Combine にはそのまま 0 をパスとして渡せばいいようだ。

$data = Set::Combine($data, '{n}.Tag.name', '{n}.0.count'); 

これでなんとか希望した配列が得られた。

Array(
  [a] => 3,
  [b] => 12,
  [c] => 8,
)

いやはやなんとも面倒だ。あらためてコードを示す。

$data = $this->Tag->find('all', 
  array(
    "fields" => array("Tag.tag", "COUNT(Tag.tag) AS `tag`"),
    "group" => array("Tag.tag"),
  )
);
$data = Set::Combine($data, '{n}.Tag.name', '{n}.0.count');
$this->set(compact('data')); 
(2011/05/27 22:56:34)
18001
プロフィール

Kenz Yamada(山田研二)。1984年生。大阪。ちょっとずつ好きなプログラム作ってます。 好きなものはカメラと旅行。ガジェットや身の回り、ちょっとこだわります。 詳しくは Web mixi で。

Bookmark and Share