Optimal way to store follower and following MySQL - php

I have 2 tables one is user and another is company. Both have the following columns common while other columns are different.
id email name
1 first#email.com First user
2 second#email.com Second User
3 third#email.com Third User
Now a user can follow many companies but a company does not follow back user. Company should have data with users who follow them and a user should also store the companies they are following.
What is the simplest and optimal to make this happen on MySQL? Either should I create separate table for it or just add a column on existing tables with array of followers. Please answer assuming I have working level of knowledge on PHP and MySQL.

You have the tables User and Company. Let's suppose they contain these values:
User
UserId
UserName
UserMail
1
Alice
alice#mail.com
2
Bob
bob#mail.com
Company
CompanyId
CompanyName
CompanyAddress
1
Microsoft
Redmond
2
Apple
Cupertino
3
Google
Mountain View
Then you should create a many-to-many table - e.g. let's call it UserCompany - which contains at least the columns UserId and CompanyId (coming from the first two tables).
Let's suppose that Alice follows Microsoft and Apple, and Bob follows Google. Your new UserCompany table will contain the following data:
UserId
CompanyId
1
1
1
2
2
3
Company should have data of users who follow them
Here you are the query to get the data of the users that follow Microsoft:
SELECT u.UserName, u.UserMail
FROM User AS u
JOIN UserCompany AS uc ON u.UserId = uc.UserId
WHERE uc.CompanyId = 1
User should also have data of companies they are following.
And here you are the query to get the data of the companies followed by Alice:
SELECT c.CompanyName, c.CompanyCity
FROM UserCompany AS uc
JOIN Company AS c ON c.CompanyId = uc.CompanyId
WHERE uc.UserId = 1

The simplest solution is to have a MANY-TO-MANY join table to link these 2 tables. You can do this with either 2 MANY-TO-MANY tables or a single one.
For example 2 table:
user_follows_company
ID CompanyID UserID
---- ------ ---------
1 1 5
1 1 6
1 1 8
1 2 5
You can get the companies a user follows by using the following SQL:
SELECT * FROM company c JOIN user_follows_company ufc on ufc.companyID = c.ID WHERE user = $USER_ID
company_follows_user
ID CompanyID UserID
---- --------- ---------
1 3 5
1 3 6
1 5 3
1 5 4
You can get the users a company follows by using the following SQL:
SELECT * FROM user u JOIN company_follow_user cfu on cfu.userID = u.ID WHERE user = $USER_ID
or you can do this with a single table and have a column that designates which direction is being followed:
follows_table
ID CompanyID UserID Initiator
---- --------- --------- ---------
1 3 5 Company
1 3 6 Company
1 5 3 Company
1 5 4 Company
1 5 1 User
1 6 1 User
1 8 1 User
1 5 2 User
Note that storing the "initiator" as a string is not a good idea - it probably should be an int or an ENUM
To query on this table, do the following queries:
Companies a user follows:
SELECT * FROM company c JOIN follows_table ft on ft.userID = c.ID WHERE user = $USER_ID AND ft.initiator = 'user'
Users a company follows:
SELECT * FROM user u JOIN follows_table ft on ft.userID = u.ID WHERE companyID = $$COMPANY_ID AND ft.initiator = 'company'

Related

fetching details of user having same reporting email address using join or alias

I have two tables
tbl_user:
id fisrtname lastname
5 John Doe
6 Peter Parker
7 Will Smith
tbl_experience:
exp_id usr_id user_reporting_to
1 5 dev#abc.com
2 6 admin#abc.com
3 7 dev#abc.com
I want to fetch those record who have same reporting email address with where condition usr_id=5 because when i am login in to my page it creates the session of user id for e.g it is now 5 in where condition using join or alias
SELECT texperience.tbl_experience_report_to_email AS tbl_experience_report_to_email,
tuser.tbl_user_fname AS tbl_user_fname,
texperience.tbl_experience_designation AS tbl_experience_designation
FROM tbl_experience AS texperience,
tbl_user AS tuser
WHERE tuser.tbl_user_fname = tuser.tbl_experience_id
AND texperience.tbl_experience_report_to_email = texperience.tbl_experience_id
AND texperience.tbl_experience_user_id = 1
SELECT tbl_user.*, tbl_experience.user_reporting_to FROM tbl_user
LEFT JOIN tbl_experience ON (tbl_user.id=tbl_experience.usr_id)
LEFT JOIN (SELECT count(*) as total_user, user_reporting_to FROM tbl_experience GROUP BY user_reporting_to) as email_group ON
(email_group.user_reporting_to = tbl_experience.user_reporting_to) WHERE email_group.total_user > 1
Basically have a subquery that group all the email address and the joined table will return those users that have emails appearing more than once in the tbl_experience.

Joining two mysql tables to get a true/false column

I'm working with PHP and MySql. I'm trying to find a way to select a number of movies from a mysql table, but apart from the movies table I have a watchlist table that stores a userID and the movieID of the movies he/she has added to his/her watchlist:
id userID movieID
=====================================
1 1 3
2 1 5
3 1 7
4 2 3
5 2 2
6 3 2
The movies table looks something like this
movieID title duration
=============================
1 tit1 34:43
2 tit2 35:43
3 tit3 24:43
4 tit4 34:13
5 tit5 11:43
6 tit6 22:43
7 tit7 33:43
The result I'm after is (for example for the user with ID 1):
movieID title duration added
=======================================
1 tit1 34:43 false
2 tit2 35:43 false
3 tit3 24:43 true
4 tit4 34:13 false
5 tit5 11:43 true
6 tit6 22:43 false
7 tit7 33:43 true
Is there a way to join both the movies and the watchlist table to produce the desired result?
Thanks.
You can get the required output by using a LEFT JOIN and then checking for a NULL in the join table.
SELECT m.*, IF(w.id IS NULL, 0, 1) AS added
FROM movies m
LEFT JOIN watchlist w ON (m.movieID = w.movieID AND w.userID = 1)
GROUP BY m.movieID

show top 5 users on logged user dashboard based on preferences

I want to show top 5 users on logged user dashboard based on following criteria:
users are opting following attributes in their profile:
Relationship preferences,
Hobbies,
Interests,
Language etc
More the preferences will match, highest priority to user's profile will be assigned
table_users
userid ufname ulname gender
--------------------------------
1 test1 Test2 M
2 testF TestF F
3 testF1 TestF1 F
4 testF2 TestF2 F
5 testF5 TestF2 F
table_preferences
preference_id user_preferences
--------------------------------
1 Cooking
2 Gardening
3 Smoking
4 Single
5 widow
6 traveling
table_user_preferences
userid user_preference_id
--------------------------------
1 1
1 2
1 3
1 4
2 3
2 4
3 2
3 3
3 6
4 1
5 1
5 2
5 3
5 4
5 6
Now, suppose user one is logged in, on his dashboard other registered users (with opposite i.e. gender female) will get display whose highest attributes are matching. As we can see, user five 5 matches most of the attributes so it will be display on top of list and rest will be get display accordingly as follows:
Result required:
User_id ufname
5 testF5
3 testF1
2 testF
4 testF2
My Query is I am thinking to use relevance search. Will it be suitable. Anyone can help me any suggestions.
Simple use MYSQL JOIN and SUBQUERY
1) Use subquery to get the preference of logged in user.
2) Then join table_user_preferences with table_users with ON tu.userid = tup.userid and AND tu.gender !=$current_user_gender and IN( ) condition to match the prefrence with logged in user preference.
3) Finally group the user and apply order by count of match preference
select tu.*,tup.userid,count(1) as total_match
from table_user_preferences as tup
join table_users as tu
ON tu.userid =tup.userid
where tup.user_preference_id
IN (select up.user_preference_id from table_user_preferences as up where up.userid=$current_userid)
AND tu.gender !=$current_user_gender
group by tup.userid order by total_match desc limit 5

Mysql query with IF

I have two tables
Users
Id user grade access_level
1 Alice 1 1
2 Charles 3 3
3 Ben 2 2
Class
Id name grade
1 biology 1
2 math 2
3 geography 2
I can read $username = $_SESSION['MM_Username'] and I want to select for each logged user a list of classes depending on their access_level. For access_level => 3 the user can see all the classes, for access_level < 3 user can see only classes with the same grade with his/hers. So:
For Charles, with access_level=3, I want this result
Id name grade
1 biology 1
2 math 2
3 geography 2
For Alice, with access_level=1 and grade = 1, I want this result
Id name grade
1 biology 1
And for Ben, with access_level=2 and grade = 2, I want this result
Id name grade
1 math 2
2 geography 2
Added from the comment
They have the access_levels based on their position in school. Let's say that Charles is a professor and Alice and Ben are students. Students can see only their classes, but the teacher can see everything.
You could use a INNER JOIN with OR:
SELECT Class.*
FROM
Class INNER JOIN Users
ON Class.grade = Users.grade
OR Users.access_level>=3
WHERE
User='username';
Please see fiddle here.
Try this.
SELECT *
FROM Users as U, Class as C
WHERE U.user = $username
AND U.access_level>=C.grade
I'm not quite sure what are you going to achieve, According to my understanding you can do something like this below.
SELECT u.user,c.name
FROM user AS u INNER JOIN class AS c ON u.grade = c.grade
WHERE u.access_level = 1 AND u.grade = 1
SELECT u.user,c.name
FROM user AS u INNER JOIN class AS c ON u.grade = c.grade
WHERE u.access_level = 2 AND u.grade = 2
SELECT u.user,c.name
FROM users AS u INNER JOIN class AS c ON u.grade = c.grade
WHERE u.grade != 3

How do I query mysql data with array

I have 2 tables colorcode & users
colorcode
ID colorid colorname
------------------------
1 1 yellow
2 2 black
3 3 red
4 4 white
users
ID userid colorid
------------------------
1 1 1,2
2 2 3,4
3 3 1,3,4
4 4 1
How do I retrieve & query individual colorid
$aa = $db->query("SELECT * FROM colorcode");
$colors = array();
while ($colordata = mysql_fetch_assoc($aa)) {
$colors[] = $colordata["colorid"];
}
Let's say I want query which users have yellow color & what it's the statement should I use for users
SELECT .. FROM users
WHERE colorid ....
It's a bad design... since you're trying to access the individual color_ids in the user table, but have stored them as a comma-separated list, you canot have the database do a normal join for you - you've killed off the main point of using a relational database by making it impossible to for the database to do the relating for you.
However, since you're on mysql, you're in luck - mysql has a function for cases like this:
SELECT users.ID, userid, GROUP_CONCAT(colorcode.colorname)
FROM users
LEFT JOIN colorcode ON FIND_IN_SET(colorcode.ID, users.colorid)
GROUP BY users.id
SELECT * FROM users
WHERE colorid LIKE "%1%"
But what I would really do is make a link table from users to colors:
usersToColors:
ID userid colorid
------------------------
1 1 1
2 1 2
3 2 3
4 2 4
...
Then you could do:
SELECT * FROM users u, usersToColors utc
WHERE u.userid = utc.userid
AND utc.colorid = 1;
Or even:
SELECT * FROM users u, usersToColors utc, colors c
WHERE u.userid = utc.userid
AND utc.colorid = c.colorid
AND c.colorname = "yellow";

Categories