0

Here I am trying shewing list sorting base in same language and hobbies the users with same language and hobbies numbers

var user_id = req.body.user_id;
    /*var sql = 'SELECT * 
        FROM `tbl_user` 
        WHERE `user_hobbies` =? 
            OR `user_language_id` = ? 
        ORDER BY `user_id` DESC';*/
     var sql ='SELECT 
        DISTINCTROW IF((pic.alloweduser_id > 0),\'1\',\'0\') AS pAccess, 
        usr.user_id AS userid,
        usr.user_name AS name,
        usr.user_gender AS gender,
        usr.user_profile_pic AS profile_pic  
        FROM tbl_user usr 
        LEFT JOIN tbl_profilepic pic 
            ON pic.alloweduser_id = usr.user_id 
        WHERE 
            `user_hobbies` LIKE CONCAT(\'%\',(
                SELECT `user_hobbies` 
                FROM tbl_user 
                WHERE user_id = ?), \'%\') 
            AND usr.`user_language_id` IN (
                SELECT `user_language_id` 
                FROM tbl_user) 
            AND usr.user_id != ? 
            ORDER BY usr.`user_name` ASC';
connection.query(sql,

I do not know what I am doing wrong , it is only working with hobbies but language still shewing users from different language

Update

  • user2 : language (1) - Hobbies (1,2,3,4)

i am trying to show users with same language (1) than users share the 4 hobbies .if not 3 hobbies ..if not 2 hobbies .. if not 1 hobbie enter image description here enter image description here

2
  • What does a typical user_hobbies entry look like for a user with multiple hobbies? It feels like it's trying to cram a one-to-many relationship into a single cell. user_hobbies might be better done as a join table. Commented Mar 9, 2018 at 21:56
  • 1
    Ok, after a second full read, I think I just absolutly don't understand how it work and what you want... Commented Mar 9, 2018 at 21:57

2 Answers 2

1

If I understand, you want to find all users which have the same language and hobbies as some other user. Stripping out all the extraneous joins to get more info about these users, we'd have...

select *
from tbl_user usr
where user_id != ?
  and user_language = (select user_language from tbl_user where user_id = ?)
  and user_hobbies = (select user_hobbies from tbl_user where user_id = ?)

But user_hobbies is a problem. It looks like a user can have many hobbies, and a hobby can have many users. That's a many-to-many relationship normally modelled as a join table. But you appear to have it as a single field with the values joined together which is going to make queries complicated. Not only because of the extra formatting and concatenation, but it will make finding intersections difficult.

For example...

user1.user_hobbies = "2,3,5"
user2.user_hobbies = "1,2,3,4,5"

user1 has a subset of user2's hobbies. But no simple string equality can figure that out. 2,3,5 is not a substring of 1,2,3,4,5.

Here's the opposite problem, a false positive.

user1.user_hobbies = "2,3"
user2.user_hobbies = "12,34"

2,3 is a substring of 12,34 so may easily get a false match.

And you have to be very careful user_hobbies is always ordered the same.

user1.user_hobbies = "1,2,3"
user2.user_hobbies = "3,2,1"

Even if user_hobbies is a JSON array and you use JSON operators, it doesn't change the fundamental problems.


The proper way to handle this is with a many-to-many table relationship.

users:
    id
    name

hobbies:
    id
    name

user_hobbies:
    user_id
    hobby_id

You'd get all a user's hobbies like so:

select u.name, h.name
from users u
join user_hobbies uh on u.id = uh.user_id
join hobbies h on h.id = uh.hobby_id
where u.id = ?

Then to find all other users who share any of a user's hobbies...

select u.id
from users u
join user_hobbies uh on u.id = uh.user_id
where uh.user_id != ?
  and uh.hobby_id in (select hobby_id from user_hobbies where user_id = ?)
group by user_id

Finding users who share all of a user's hobbies is a little more complicated. You do a group by of all user/hobby combinations that match, then check for the ones which had the same number of hobbies as the user. This is a bit easier using a with clause to avoid repeating the same subselect.

with my_hobbies as (
    select hobby_id from user_hobbies where user_id = ?
)
select uh.user_id
from my_hobbies mh
join user_hobbies uh on uh.hobby_id = mh.hobby_id
where uh.user_id != ?
group by uh.user_id
having count(*) = (select count(*) from my_hobbies);

This might seem complicated, and it is. And using a JSON array might seem simpler, and it is. But ultimately the effort to learn how to work with join tables is worth it. They will produce the right results and less headaches.

Sign up to request clarification or add additional context in comments.

1 Comment

thank you so much , i updated the question with table images
0

Change this:

AND usr.`user_language_id` IN (
    SELECT `user_language_id` 
    FROM tbl_user) 

To:

AND usr.`user_language_id` IN (
    SELECT `user_language_id` 
    FROM tbl_user
    WHERE user_id = ?) 

And If I understand what you want, it should do it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.