views:

154

answers:

3

What I'm trying to do is pull up profile info w/ the profile's comments. I get everything as expected. No error returned, array is formatted perfectly. My concern is the queries that are run. It runs one query for each ID to get its photo (the start of the query is noted in comments in the code below). I guess this is the only way to get photos by user_id? All in separate queries? Is there a better way?

I'm picturing a profile with 40+ comments and it's scary to imagine. Is this where memcached comes in?

$profile = $this->Profile->find('first', array(
                            'conditions' => array('Profile.url' => $url),
                            'contain' => array(
                                    'User' => array(
                                            'fields' => array(
                                                    'User.id','User.name'
                                            ),
                                            'Photo' => array(
                                                    'fields' => array(
                                                            'Photo.thumbnail','Photo.image'
                                                    )
                                            )
                                    ),
                                    'Comment' => array(
                        'User' => array(
                            'fields' => array(
                                'User.name'
                            ),
                            'Photo' => array( // right here
                                'fields' => array(
                                    'Photo.thumbnail'
                                )
                            )
                        )
                    )
                            )
                    )); 

edit:

I obviously have a User table, as well as a Comment table. I also have a Photo table that stores URL's of the users images, foreign key = user_id. So while i query all Comments from a specific profile and it's Comment.user_id, I also need to grab the Photo.thumbnail from the Photo table by its user_id.

+1  A: 

You can make it much faster using a LEFT JOIN.

edited code has been edited to better respond to the question (two left joins are needed - not one).

SELECT c.text, i.profiles, p.photo_url
FROM comments AS c
LEFT JOIN profiles AS i on c.profile_id = i.id
LEFT JOIN photos AS p ON i.id = p.user_id
WHERE c.post_id = 32
LIMIT 20

This is just a generic SQL but would:

  1. pull all comments (in the comments table) bellowing to article 32
  2. left join the profiles table matching the comment poster id to the comment
  3. pull the first 20 comments

And with only one query you would pull all 30 comments + their associated profiles.

Hope it helps!

Frankie
Hey, Frankie thanks for responding. I think I need to explain my situation more clear. I obviously have a User table, as well as a Comment table. I also have a Photo table that stores URL's of the users images, foreign key = user_id. So while i query all Comments from a specific "Article" as you say, I also need to grab the Photo.thumbnail from the Photo table by its user_id. Sorry for the confusion, I'll edit my original post to make it clearer for others.
centr0
No problem! Make it two LEFT JOINS! I'll edit the example.
Frankie
Awesome! Thanks! One more thing. ive edited the query somewhat for my app but when i query for the comments im also trying to get the user name so i tried:SELECT c.content, c.created, c.modified, p.thumbnail, u.nameFROM comments AS cLEFT JOIN profiles AS i ON c.profile_id = i.idLEFT JOIN photos AS p ON i.id = p.user_idLEFT JOIN users AS u ON p.user_id = u.idWHERE c.profile_id = 1but it shows the same u.name and maybe the same p.thumbnail. thanks so much for your help.
centr0
got it: SELECT c.content, c.created, c.modified, p.thumbnail, u.nameFROM comments AS cLEFT JOIN profiles AS i ON c.profile_id = i.idLEFT JOIN users AS u ON c.user_id = u.idLEFT JOIN photos AS p ON u.id = p.user_idWHERE c.profile_id =1Thanks for the push in the right direction. I seriously need to learn SQL in depth. :/
centr0
Can anyone tell me how to do this the cake way? While custom queries are awesome, I'd like to see if there's a CakePHP way in doing this. If I'm not using Cake's ORM for this I might as well use CI.
centr0
+1  A: 

You can replace the array key 'contain' with the array key 'link', and it builds the left joins for you - see linkable behavior. The downside is that all relations linked must be from the hasOne or hasMany to the belongsTo relation.

michaelc
I found the Linkable behavior earlier today. Just can't get it to work the way I want to. It's fine pulling up tables at a direct relationship. But once it starts going beyond recursive level 1 it craps out and I don't get any results. Maybe I'm doing something wrong. Been at this for days trying to get it right before I move on because this type of query is similar to the other queries I'll run in this web app. Frustrating!!
centr0
+1  A: 

You might also want to look at Nate's article in the Bakery about doing joins "the cake way".

http://bakery.cakephp.org/articles/view/quick-tip-doing-ad-hoc-joins-in-model-find

Martin Westin