Cakephpで普通にINNER JOINする
タイトルが微妙すぎて困る!
CakePHPのアソシエーションを使うと、基本LEFTでテーブルをJOINしてfindなどされると思います。
これをINNER JOINにしたい!といっても、hasOneとbelongsToでtype=>”INNER”を指定すればINNER JOINできるのは周知の事実でございますが、hasManyでできねーのかよ!って思って触ってたら案の定できたのでメモ。
まぁSum limitedさんところで書いてある方法にほとんど近いのですが、beforeFindに書くと別のfindでも使ってしまうし、うーんと思ってたんだけど、findAllじゃなくてfindを使えば大丈夫そうなんですよ。
テーブル
mysql> desc users; +----------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+------------------+------+-----+---------+----------------+ | id | int(11) unsigned | NO | PRI | NULL | auto_increment | | name | varchar(255) | NO | | | | | modified | datetime | YES | | NULL | | | created | datetime | YES | | NULL | | +----------+------------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec) mysql> select * from users; +----+------+---------------------+---------------------+ | id | name | modified | created | +----+------+---------------------+---------------------+ | 1 | a1 | 2008-11-17 08:33:12 | 2008-11-17 08:33:12 | | 2 | b1 | 2008-11-17 08:33:12 | 2008-11-17 08:33:12 | +----+------+---------------------+---------------------+ 2 rows in set (0.00 sec) mysql> desc user_comments; +----------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+------------------+------+-----+---------+----------------+ | id | int(11) unsigned | NO | PRI | NULL | auto_increment | | user_id | int(11) unsigned | NO | MUL | 0 | | | comment | varchar(255) | NO | | | | | modified | datetime | YES | | NULL | | | created | datetime | YES | | NULL | | +----------+------------------+------+-----+---------+----------------+ 5 rows in set (0.00 sec) mysql> select * from user_comments; +----+---------+---------+---------------------+---------------------+ | id | user_id | comment | modified | created | +----+---------+---------+---------------------+---------------------+ | 1 | 1 | aee | 2008-11-17 08:34:02 | 2008-11-17 08:34:02 | | 2 | 1 | addd | 2008-11-17 08:34:02 | 2008-11-17 08:34:02 | | 3 | 1 | accdd | 2008-11-17 08:34:02 | 2008-11-17 08:34:02 | | 4 | 2 | brree | 2008-11-17 08:34:02 | 2008-11-17 08:34:02 | | 5 | 2 | bbawwaa | 2008-11-17 08:34:02 | 2008-11-17 08:34:02 | | 6 | 2 | bqwedf | 2008-11-17 08:34:02 | 2008-11-17 08:34:02 | +----+---------+---------+---------------------+---------------------+ 6 rows in set (0.00 sec)
今回使うのは2つ。usersとuser_commentsテーブル。
こいつをuserのモデルでuser_commentsをINNER JOINしてデータをひっぱってくる。
$fields = array( "conditions" => array("User.id=1"), "fields" => null, "limit" => 5, "order" => null, "joins" => array( array("type" => "INNER", "table" => "`user_comments`", "alias" => "UserComment", "conditions" => "`User`.`id`=`UserComment`.`user_id`", ), ), ); $result = $this->User->find("all", $fields);
まぁ前回のコードの使いまわしですが気にしない。
fieldsにjoinsがあるので、そこで配列の中に配列でJOINするテーブルを指定すればOK。
まーわかると思うけど
・type → INNER / LEFT
・table → 接続したいテーブル名
・alias → テーブル名のエイリアス。as ~の~にあたる部分。
・conditions → JOINのONにあたる部分を記述。
です。
結果はこちら。
Array
(
[0] => Array
(
[User] => Array
(
[id] => 1
[name] => a1
[modified] => 2008-11-17 08:33:12
[created] => 2008-11-17 08:33:12
)
)
[1] => Array
(
[User] => Array
(
[id] => 1
[name] => a1
[modified] => 2008-11-17 08:33:12
[created] => 2008-11-17 08:33:12
)
)
[2] => Array
(
[User] => Array
(
[id] => 1
[name] => a1
[modified] => 2008-11-17 08:33:12
[created] => 2008-11-17 08:33:12
)
)
)JOINはできてる!・・・けど、user_commentsがとれてないじゃん!ってことです。
これが注意点ですね。fields(取得するパラメータ)をnullにしてしまうと、JOINの元となるテーブルしかひっぱってこないのです!
ちなみにクエリはこんなの
SELECT `User`.`id`, `User`.`name`, `User`.`modified`, `User`.`created` FROM `users` AS `User` INNER JOIN `user_comments` AS `UserComment` ON (`User`.`id`=`UserComment`.`user_id`) WHERE `User`.`id`=1 LIMIT 5
Userの部分しかひっぱってきてないのがわかりますね。なので、joins使って指定するときはちゃんと「*」なり、「User.*」など、普通のクエリを書くように注意しましょう。
あとちなみに、joinsの中のjoinテーブルを追加すると、多重接続もできるよ!!
"joins" => array( array("type" => "INNER", "table" => "`user_comments`", "alias" => "UserComment", "conditions" => "`User`.`id`=`UserComment`.`user_id`", ), array("type" => "INNER", "table" => "`user_skills`", "alias" => "UserSkill", "conditions" => "`User`.`id`=`UserSkill`.`user_id`", ), ),
こんな感じってことです。
今年の更新はこれで終わり!
あまり更新できなかったけど、まぁこんなもんかなー!
来年はMySQLクラスターとかで遊びたいな!
それでは皆様よいお年を!
Categories: cakephpTags: cakephp
コメントはまだありません »
このコメント欄の RSS フィード — トラックバック URL
コメントはまだありません。
コメントをどうぞ