cakePHP で GROUP BY の壮絶バッドノウハウ 4

いろいろなところで紹介されているように
普通に $condition の中にぶちこめばいけるんですが、
こんなかんじ

$this->モデル->findAll(
        $conditions = “GROUP BY title”,
        $limit = “”
);

例えばINとか、LIKEとか使ってごりごりやっていくときって
Array で $condition つっこむのでそれのやり方のお話

普通にやると

$this->モデル->findAll(
        $conditions = array(‘Table.uid’ => Array , ‘GROUP BY Table.title’),
        $limit = “”
);

こんなかんじで、Arrayの一つとして GROUP BY を渡せばいいと思うんですが、
これじゃうまくいきません。
なぜなら Array の要素はすべて AND でつなげてしまうから。

つまりこれをSQLにすると

WHERE Table.uid=1 AND GROUP BY Table.title

なんていうSQLを投げてしまうわけです。
もちろんエラーに。

で これをどう解決するかというと
こういう風にできます


$this->モデル->findAll(
        $conditions = array(‘Table.uid’ => Array , ‘Table.a<>”” GROUP BY Table.title’),
        $limit = “”
);

*2008/03/03追記
コメントをいただいたので修正してみました。

$this->モデル->findAll(
        $conditions = array(‘Table.uid’ => Array , ‘1=1 GROUP BY Table.title’),
        $limit = “”
);

わかるかな。。。
*Table.a<>”” という条件はほしいデータの抽出にまったく影響しないダミー条件です(なんでもいいんだけど)

*2008/03/03追記
自前の1100万件のレコードのあるテーブルで上の二つをExplainしてみると
table type possible_keys key key_len ref rows Extra
Table_Name ALL NULL NULL NULL NULL 11006100 Using where
Table_Name ALL NULL NULL NULL NULL 11006108
となります。

ようは Table.a<>“” というのはWHERE句として解析して
その後で出力するんですが、
WHERE 1=1 はWHERE句の処理をせずに、無視してSQLを解析するので、
早くなります。
従って処理速度は table.a<>“” を使った時より圧倒的に早くなります。

ちなみに WHERE 1 でもOKだったので文字数を減らすならこうなります。

*2008/03/03追記
$this->モデル->findAll(
        $conditions = array(‘Table.uid’ => Array , ‘1 GROUP BY Table.title’),
        $limit = “”
);

Table.a<>”” をGROUP BY に書き加えただけなんですが、
これでうまくいきます。
ようは

WHERE Table.uid=1 AND Table.a<>”” GROUP BY Table.title

というSQLの正しい構文にするためにダミーの条件を GROUP BY が入ってるArrayのとこに書き加えてあるんです。
なんという力技。。。

ダミー条件とはいえ若干だろうけど負荷も大きくなるし、
もちろん激しく無駄w

そのままSQLかけという話もありますが
こういう方法もありますということで。


->