Update: I figured it out. See my answer below.
I'm trying to write some logic at the application level to identify the friends (mutual followers)in the table below. My query has returned the data in a format similar to the table below (borrowed from this question, but I don't need a query, that part's done):
A B
1 2 // mutual followers, so "friends"
2 1 // mutual followers, so "friends"
1 3 // user 1 is following 3
1 4 // user 1 is following 4
So how can I write some logic which shows the users where A = B and B = A, but in different rows? Using PHP/codeigniter.
In response to a request, here's the SQL tables and query:
Users table - uid, fname, lname
Followers table - user_id, follow_id
Select users.uid, users.fname, users.lname, u.uid, u.fname, u.lname
FROM users
INNER JOIN follows f on (f.user_id=users.uid)
INNER JOIN users u on (u.uid=f.follow_id)
I think you want something like this:
$results = array(array(1,2),array(2,1),array(1,3),array(1,4));
$mutual_users = array_filter($results,function($elem)use($results){
if(in_array(array_reverse($elem),$results)){
return true;
}
});
print_r($mutual_users);
Okay, I figured it out. I needed a second INNER JOIN for the followers table. I added the code below to my SQL query, and it worked.
INNER JOIN followers f2 ON u.id = f2.user_id AND users.id = f2.follow_id
Related
table posts
table users
how would i count posts for specific user logged in. for example when user with id 3 is logged in it should show me 4 posts
I already did it for total posts count:
<?php
$post_query1 = "SELECT count(*) AS total FROM posts ";
$post_result1 = mysqli_query($db, $post_query1);
$post1 = mysqli_fetch_array($post_result1);
?>
Try below example :
select count(*) as total from user as u inner join post as p on p.id_user = u.id_user AND u.id_user = 3
If you want to get only the posts count for the particular user, say user with id = 3, your query should be this:
$query = "SELECT count(*) AS total FROM posts WHERE id_users = 3";
But if you want to get both the posts count as well as the user information and other post information, you will have to run a join query on both the users and posts table. Your query would now become:
$query = "SELECT u.*, p.*, count(p.id_posts) FROM users AS u JOIN posts AS p ON u.id_users = p.id_users WHERE p.id_users = 3";
Some Useful Notes
p.* - * is a wildcard character that means get all the columns in the posts table
u.* - * is a wildcard that means get all the columns in the users table
posts as p - AS is for aliasing. So, we are giving posts table a temporary name.
Here are the different types of the JOINs in SQL:
(INNER) JOIN: Returns records that have matching values in both tables
LEFT (OUTER) JOIN: Return all records from the left table, and the matched records from the right table
RIGHT (OUTER) JOIN: Return all records from the right table, and the matched records from the left table
FULL (OUTER) JOIN: Return all records when there is a match in either left or right table
Note: It is necessary that you have to join two/more tables only with the help of foreign key. Without the foreign key is is meaningless to join two or more tables
Reference 1: https://www.w3schools.com/sql/sql_join.asp
Reference 2: https://www.tutorialspoint.com/mysql/mysql-using-joins.htm
As per the Question what you have asked to join the tables
Query:
SELECT * FROM TABLE 1 JOIN TABLE 2 ON TABLE1.id = TABLE2.id WHERE TABLE2.ID=3
Kindly replace TABLE1 & TABLE2 with the Tables that are to be joined and the id with the foreign key what you have specified in the Table.
Hope so this might be helpful for you to write your own code in future. Happy Coding :)
You have only to use a simple join.
SELECT count(*)
FROM USER u,
post p
WHERE p.id_user = u.id_user
AND u.id_user = 3
I'm trying to show relation between two users. I want to insert only one row to Relations table (see structure below). But my script is showing that user B is friend of himself - that's not right.
This is a structure of my database (with examples):
Users
id|email|password|name|pic_url|friend_count
1 |a#.. |aaaaaaaa|A |http...|1
2 |b#...|bbbbbbbb|B |http...|0
Relations
id|user_id|friend_id|status(0 and 1)
1 |1 |2 |1(if accepted)
What am I doing wrong? Here's my query:
SELECT Relations.friend_id, Users.name,Users.email,Users.pic_url FROM Relations
INNER JOIN Users
ON Relations.friend_id = Users.id
WHERE Relations.user_id = $user_id
OR Relations.friend_id = $user_id
AND Relations.status = 1
I recommend to insert two rows into Relations table.
id|user_id|friend_id|status(0 and 1)
1 |1 |2 |1(if accepted)
2 |2 |1 |1(if accepted)
For example, user A send friend request to B. Until B accept this request, the status of both rows would be 0.
Query for accepting: (user B)
UPDATE Relations SET status=1 WHERE (user_id=$user_id AND friend_id=$friend_id) OR (user_id=$friend_id AND friend_id=$user_id)
Query for selecting:
SELECT Relations.friend_id, Users.name, Users.email, Users.pic_url FROM Relations
INNER JOIN Users
ON Relations.friend_id = Users.id
WHERE Relations.user_id = $user_id
AND Relations.status = 1
Update: If you really want to insert only one row, you would need to execute two queries - the one for the friends user B added and another one for the friends that has added User B to their friend list.
SELECT Relations.friend_id, Users.name, Users.email, Users.pic_url FROM Relations
INNER JOIN Users
ON Relations.friend_id = Users.id
WHERE Relations.user_id = $user_id
AND Relations.status = 1
SELECT Relations.user_id, Users.name, Users.email, Users.pic_url FROM Relations
INNER JOIN Users
ON Relations.user_id = Users.id
WHERE Relations.friend_id = $user_id
AND Relations.status = 1
Your problem is that you're selecting friend_id which means that if you execute your query as user B, the friend_id would be 2 - user B. (see your table example)
You should take a look to this question for more information about performance.
I am trying to build an ajax chat system. Basically I have 2 tables, the users table and the pm (private messaging) table. I am joining these tables.
How can I get all the information from the users table for person 1, and person 2 (receiver and sender) in one query so I can order all the chats by the correct time?
I tried using the normal join to get this done, but I have realised that it sends only one set of data from the users table. Is it possible to join the same table twice?
I have tried this:
SELECT pm.id, pm.message, pm.reciever, pm.sender, pm.senttime, pm.rread,
u.username, u.name, u.surname, u.fullname, u.profile, u2.username, u2.name,
u2.surname, u2.fullname, u2.profile
FROM pm, users u, users u2
WHERE (pm.reciever = 1 AND pm.sender = 2) OR (pm.reciever = 2 AND pm.sender = 1)
But it is returning multiples.
You have to compare your ids from the different tables:
SELECT pm.id, pm.message, pm.reciever, pm.sender, pm.senttime, pm.rread, s.username, s.name, s.surname, s.fullname, s.profile, r.username, r.name, r.surname, r.fullname, r.profile
FROM pm, users s, users r
WHERE (r.id = pm.reciever) AND (s.id = pm.sender) AND ((r.id = 1 AND s.id = 2) OR (r.id = 2 AND s.id = 1))
I have a query that retrieves the users that are online, and a users friends. Now I want to know the best way to combine the two so I can get the results of the users friends that are online.
Friends query:
SELECT
CASE WHEN userID=$session
THEN userID2
ELSE userID
END AS friendID
FROM friends
WHERE userID=$id OR userID2=$session
LIMIT 18
users online:
SELECT *
FROM usersActivity
WHERE setActivity!=3
AND userID!=$session
usersActivity.userID needs to match friendID
Query should be:
SELECT users.name
FROM usersActivity
INNER JOIN friends ON
(usersActivity.userID = usersActivity.userID AND usersActivity.userID2 = $session) OR
(usersActivity.userID2 = usersActivity.userID AND usersActivity.userID = $session)
INNER JOIN users ON
(usersActivity.userID = users.userID) OR
(usersActivity.userID2 = users.userID)
WHERE usersActivity.setActivity!=3
AND usersActivity.userID!=$session
AND users.userID != $session
GROUP BY users.id
You may use COUNT(user.id) if you want only count of users. Or select all names (store them for later use in listing) and use only mysql_num_rows() for getting actual number of friends online
I think I understand what your after:
SELECT userID FROM usersActivity
WHERE setActivity !=3
AND userID IN(
(SELECT userID FROM friends WHERE userID2=$id)
);
This assumes you have double rows for your friend linking table and $id is the current logged in user.
userID userID2
1 2
2 1
Using subqueries in your where statement should consolidate this. Not sure if this will be faster or not, depends on how you are doing things so profile it. You can join on your users table to get the friends name information and what other info you need.
Im trying to construct a query that goes over 3 tables and im COMPLETELY stumped ... my knowledge limit is basic 1 table query and i need some help before i stick my head in a blender.
I have the following query
SELECT * FROM internalrole WHERE introle = $imarole
Im fine with that part .. its the next thats getting me all stressed.
That query returns the following columns ( id, user_id, introle, proven, used )
What i then need to do is take the user_id from the results returned and use it to get the following
SELECT * FROM users WHERE id = user_id(from previous query) AND archive = 0 and status = 8
I need to put that into 1 query, but wait, theres more .... from the results there, i need to check if that user's 'id' is in the availability table, if it is, check the date ( column name is date ) and if it matches todays date, dont return that one user.
I need to put all that in one query :S ... i have NO IDEA how to do it, thinking about it makes my head shake ... If someone could help me out, i would be eternaly grateful.
Cheers,
Use INNER JOIN, which links tables to each other based on a common attribute (typically a primary - foreign key relationship)
say an attribute, 'id', links table1 and table2
SELECT t1.att1, t2.att2
FROM table1 t1
INNER JOIN table2 t2
ON t1.id = t2.id --essentially, this links ids that are equal with each other together to make one large table row
To add more tables, just add more join clauses.
SELECT u.*
FROM internalrole ir
INNER JOIN users u
ON ir.user_id = u.id
AND u.archive = 0
AND u.status = 8
LEFT JOIN availability a
ON ir.user_id = a.user_id
AND a.date = CURDATE()
WHERE ir.introle = $imarole
AND a.user_id IS NULL /* User does NOT exist in availability table w/ today's date */
EDIT: This second query is based on the comments below, asking to show only users who do exist in the availability table.
SELECT u.*
FROM internalrole ir
INNER JOIN users u
ON ir.user_id = u.id
AND u.archive = 0
AND u.status = 8
INNER JOIN availability a
ON ir.user_id = a.user_id
WHERE ir.introle = $imarole
Hmm, maybe something like this
SELECT * FROM users WHERE id IN (SELECT user_id FROM internalrole WHERE introle = $imarole) AND archive = 0 and status = 8;
A handy thing for me to remember is that tables are essentially arrays in SQL.
HTH!
Nested queries are your friend.
SELECT * FROM users WHERE id in (SELECT user_id FROM internalrole WHERE introle = $imarole) AND archive = 0 and status = 8
Alternatively joins:
SELECT * FROM users INNER JOIN internalrole ON users.id = internalrole.user_id WHERE internalrole.user_id = $imarole AND users.archive = 0 and users.status = 8