问题
I'm making a dating application, much like tindler. Users can like or dislike other users, and if two users both like each other they get the option to chat with eachother. Currently building the query to pull a random profile and one of their pictures at random:
$data = $this->db
->select('users.id,display_name,city,state,gender,users_pictures.picture')
->join('users_pictures','users_pictures.user_id = users.id')
->order_by('id','RANDOM')
->limit(1)
->where(array('users.approved'=>1,'users_pictures.approved'=>1))
->where(array('users.id !='=>$user_id))->get('users')->result_array();
Now here's where I'm confused.. I have a table for likes_dislikes that consists of user_id, foreign_user_id, and event_type (like, dislike).
If you disliked or liked a user already, I do not want them in my results. The only means I can think of handling this is to perform a second query which checks this, and then does another 'random' query if you have already liked/disliked them so that you only see users you haven't already rated. Is there a better way?
Any help is much appreciated :)
回答1:
Have you heard of the EXISTS
and NOT EXISTS
MySQL
commands? The latter is the one you should try.
SELECT
u.id, display_name, city, state, gender, up.picture
FROM
users AS u
INNER JOIN
users_pictures AS up ON up.user_id = u.id
WHERE
NOT EXISTS(
SELECT
1
FROM
likes_dislikes
WHERE
ld.foreign_user_id = u.id AND ld.user_id = $loggedInUserId
)
The above will list all users, excluding all liked/disliked users. Trying to form this SQL
statement with Codeigniter
without the value being binded is a little hacky.
A brief investigation via Google (which may now be outdated) suggests that the following should be suitable.
//...rest of query
$db->where("
NOT EXISTS (
SELECT 1
FROM likes_dislikes
WHERE ld.foreign_user_id = u.id AND ld.user_id = $loggedInUserId
) AND 1 = ", 1);
Take notice to the last part AND 1 = ", 1);
.
回答2:
This is not an answer, but I have little suggestion.
You can change like/dislike to numbers, -1 (dislike), 0 or NULL (unrated), 1 (like) for example.
It should simplify/shorten your queries.
After this - you can create view/query (or even better - SQL function) that will compute sum of ratings of 2 users, and sum like this may be used for many tasks if you think about it.
回答3:
If you use a left outer join you will get the records in the left table that DO NOT have a match in the right table. (As outlined here http://www.khankennels.com/blog/index.php/archives/2007/04/20/getting-joins/)
You can specify this join type via the third parameter of CodeIgniter's active record join() function.
Thus, try using something like:
$data = $this->db
->select('users.id,display_name,city,state,gender,users_pictures.picture')
->join('users_pictures','users_pictures.user_id = users.id')
->join('likes_dislikes', 'likes_dislikes.user_id = users.id', 'left outer')
->order_by('id','RANDOM')
->limit(1)
->where(array('users.approved'=>1,'users_pictures.approved'=>1))
->where(array('users.id !='=>$user_id))->get('users')->result_array();
来源:https://stackoverflow.com/questions/16680676/codeigniter-complex-join-only-if-rows-dont-exist