Mysql: Many to Many query based on Array - php

I have a database with 4 tables:
users following
------------- --------------------------------
| id | etc.. | | user_id (FK) | follow_id (FK) |
articles article_relations
------------- --------------------------------
| id | etc.. | | user_id(FK) | article_id (FK) |
Users can follow other users so they can see what articles they saved.
So based on the current user id it needs to check which users he/she follows in the table "following". The users that are followed will be known now.
Based on those follower ids it needs to check in article_relations which article id's are linked in article_relations to the followers. Now it should now which articles are saved by which users.
So now in the table articles the article_ids needs to be queried keeping the information which user the article saved.
Is the database design logical?
It seems to me that querying the "stream" to see which articles the users you follow saved is very redundant.
Can someone tell me if the DB Design is OK and help me with the query to get the articles from
the users you follow including the user info?
I tried till my pants fell off and searched whole stackoverflow!

try this query, it'll get you user's information, and the people the current user is following's information and the articles that are saved by the people the current user is following.
SELECT u.*,
fu.*,
a.*
FROM following f
INNER JOIN users u ON u.id = f.user_id
INNER JOIN users fu ON fu.id = f.follow_id
INNER JOIN article_relations ar ON ar.user_id = f.follow_id
INNER JOIN articles a ON a.id = ar.article_id
WHERE f.user_id = <currentUserId>
just change the .* to fields you need from each table.

Structure looks fine to me. As for the query, try this.
Join the following table (a) to the article_relations table (b)
by way of the follow_id then joining that to the article table (c) by article_id all based on the current user id.
I'm including the fictional fields article_name and article_field just as an example of what you might be pulling from the article table.
select c.id,
c.article_name,
c.article_field
from (following a
join article_relations b on a.follow_id = b.user_id)
join articles c on b.article_id = c.id
where a.user_id = current_user_id;

Just need to add the users table (d) into the mix for that.
select c.id,
c.article_name,
c.article_field,
d.id
from ((following a
join article_relations b on a.follow_id = b.user_id)
join articles c on b.article_id = c.id)
join users d on a.user_id = d.id
where a.user_id = current_user_id;

Related

(SQL) Get friends where user and friends are in 2 different tables

I've got 2 tables: users & friends. I want to show each profile picture of the friends of the logged user, but loggedUser-friends match is in a different table (which is friends) than the one that contains the URI to the profile pictures (which is users).
My query now looks like this:
SELECT profile_picture FROM users WHERE
And now I have to complete the WHERE clause:
friend's table schema is the following:
id | user_id | friend_id
friends table's sample data:
1 | pino20 | sebo14
while users' table schema is
id | user_id | profile_picture
users table's sample data:
1 | pino20 | pino20/profile.jpg
With below query you get your frends userid and their profile picture.
select user_id , profile_picture from users WHERE user_id in( select friend_id from friends where user_id=$your_userid)
Above result can be achieved using join
SELECT NT.profile_picture FROM users AS NT JOIN friends AS FR ON FR.id = NT.id
You can achieve this by using joins. It should look like this:
EDIT:
SELECT user.profile_picture,user_friend.profile_picture
FROM user
JOIN friend ON user.user_id = friend.user_id
left join user user_friend on user_friend.friend_id=friend.user_id -- left join since we don't want to drop records if there is no match

Query to fetch data from two different tables

I have two tables. Table A and B.
I have a log-in form where I will get the username,password, assign, assign2 of the user from table A and fetch data depending on the user's assign1 and assign2 from table B.
How my query would look like?
Looking for answers. Thankyou so much.
Table A -THIS IS THE TABLE FOR LOG-IN FORM
==========================================
username | password | assign1 | assign2 |
------------------------------------------
SANDRA | SANTOS | 1 | 1 | //Values
--------------------------------------------
Table B -
=======================================
name | assign1 | assign 2 |
------------------------------
DADA | 1 | 1 | //this will be displayed
------------------------------
gorg | 2 | 2 |
//this must not be displayed since the user assign1 and assign2 who logged in did not match to this
You are using $sql variable in
$result = $con->query($sql);
It should be $queryagain.
Your question is not clear, but if you want to fetch data from Table B which depends on assign1 and assign2 you can do it like this:
$queryagain = mysqli_query("SELECT * FROM tableB INNER JOIN tableA ON tableB.name=tableA.username WHERE tableA.assign1 = tableB.assign1 AND tableA.assign2 = tableB.assign2");
When you use JOIN it's best practice to JOIN by primary key (id). If tableB.name=tableA.username are not columns with same value you can join by other columns, like assign1, or assign2:
assign1:
$queryagain = mysqli_query("SELECT * FROM tableB INNER JOIN tableA ON tableB.assign1=tableA.assign1 WHERE tableA.assign2 = tableB.assign2");
assign2:
$queryagain = mysqli_query("SELECT * FROM tableB INNER JOIN tableA ON tableB.assign2=tableA.assign2 WHERE tableA.assign1 = tableB.assign1");
Notice: Where clause is not necessay, you can edit WHERE clause depends of the result you want.
I think your are very very new to database programing. First of all I recomend you to read https://www.w3schools.com/sql/sql_join.asp this page and work on examples using try it yourself part.
Join Types:
INNER JOIN: Returns records that have matching values in both tables. That means if assign field is filled in Table A and the value is included in table B then this type of join should match the rows.
LEFT JOIN: Return all records from the left table, and the matched records from the right table. That means all rows in Table A will match either the value is included in table B or not.
RIGHT JOIN: Return all records from the right table, and the matched records from the left table. That means all rows in Table B will match either the value is included in table A or not.
FULL JOIN: Return all records when there is a match in either left or right table. All rows in table A and table B will be included in te result set either they match or not.
Your SQL query may look like:
$sql = "SELECT * FROM table_a a INNER JOIN table_b b on a.assign1 = b.assign1 INNER JOIN table_b b2 on a.assign2 = b2.assign2";
execution part of the sql can be different depending your database engine or other libraries.
I think this thread also helps you: Join two mysql tables with php

how to filter results from mysql inner join query

I have got a problem with my many to many relationship.
Client table columns:
clientID, name, address etc.
User table columns:
userID, name, address etc.
Users_clients columns:
userID, clientID.
Each client can have multible users attached and users can have multible clients.
Right now my users_clients table contains this:
userID | clientID<br>
1 | 2
1 | 3
2 | 2
2 | 3
3 | 3
3 | 2
4 | 1
On my php page I want a list of users which is not already attached to the client.
Ex. if I click on the client profile which has clientID = 3
It should show me a list of users not attached to this client.
SELECT u.name, u.email, u.userID FROM users u
INNER JOIN users_clients uc
ON u.userID = uc.userID
WHERE uc.clientID !=3
This works fine, but how do I create my MySQL query so that if a user have both clientID 3 and client 2 it doesn't show.
This query shows
1|2
2|2
3|2
4|1
and what I'm seeking is:
3|2
4|1
Hope this makes sense to you. Feel free to ask :)
You could process differently.
First make a request to seek every user with a clientId = 3;
select u.id from users u
INNER JOIN users_clients uc
ON u.userID = uc.userID
WHERE uc.clientID =3;
And then you could use this request to fetch all the users except those who have a clientId = 3.
Final request looks like this :
select u.id from users u where u.id NOT IN (select u.id from users u
INNER JOIN users_clients uc
ON u.userID = uc.userID
WHERE uc.clientID =3);
hope this'll help;
Have you tried a DISTINCT instruction ?
select distinct u.id from users u
INNER JOIN users_clients uc
ON u.userID = uc.userID
WHERE uc.clientID =3;

Getting records from more than 2 tables using join

Here is my table structure:
Table 1
id | question | posted_id
Table 2
id | username | email
Table 3
id | reader_id | quote_id
I want to fetch those question which are not read by particular user.I also want email from table2 in result set. So I created Below query that join my two table1 and table2.
My query:
SELECT table1.id,table1.question,table1.posted_id,table2.email
FROM table1,table2
WHERE table1.post_id = table.id;
How to fix a left join on table 3 for filter the records Because I need questions which are not read by particular user.
I am not sure which user field you are trying to match against, i have taken email, Also this will only give matching records, Try
SELECT T1.*,T2.email
FROM Table1 AS T1
INNER JOIN Table2 AS T2 ON T2.quote_id = T1.id
INNER JOIN Table3 AS T3 ON T3.reader_id = T2.id
WHERE T2.email='some_mail_id'

MySQL Table Joins

I have a table which links the userID and the friendID (which is another user) to say they are friends.
If User 1 adds User 24 as their friend, the first row in the below table will happen
If User 10 adds User 1 as their friend, the second row in the below table will happen
From there, even if User 1 is on either side, they are friends with the adjacent ID.
FRIENDS TABLE:
userID | friendID
-----------------
1 | 24
10 | 1
What I need to do now is: If User 1 is logged in, I need to display the people they are friends with. This query I have wrote:
SELECT DISTINCT (Users.username), friends.userID, friends.friendID FROM Users, friends WHERE Users.userID IN(SELECT userID FROM friends WHERE Users.userID = friends.userID) OR Users.userID IN(SELECT DISTINCT(userID) FROM friends WHERE Users.userID = friends.friendID)
Will bring back:
username | userID | friendID
-----------------------------
name1 | 10 | 1
name1 | 1 | 24
name2 | 10 | 1
name2 | 1 | 24
name1 = ID 1
name2 = ID 10
Is there a way where I can retrieve the logged in Users'friends (e.g. if ID #1 is logged in) whether they appear in the userID or friendID columns. and then, in this case, retrieve ID 24 and 10 because they are linked with ID #1, and then when it comes to displaying, eliminate ID # 1 from the list because it will bring up that they are friends with themselves.
Hope this makes sense and thank you in advance!
SELECT DISTINCT s.FriendId
FROM (
SELECT f.FriendId
FROM Friends f
WHERE f.UserId = #id
UNION ALL
SELECT f.UserId
FROM Friends f
WHERE f.FriendId = #id
) s
WHERE s.FriendId != #id
You may not need the last WHERE given that a user probably is not adding himself or herself as a friend.
While the way you are storing data may seem efficient, the following may be a better approach:
When a MUTUAL friendship is formed, enter the data twice: once as userID(1) friendID(24) and once as userID(24) friendID(1). The reason this approach may be good is that it makes your table reusable.
Presently your table is like facebook: if I am your friend then perforce you are also my friend: I see your activities; you see my activities. The design I explain allow you to use the table as both facebook and twitter: just because you are following my activities does not mean I want to follow yours.
Here's an easy way to do it with UNION. This also takes care of duplicates:
(SELECT userID
FROM friends
WHERE friendID = 1)
UNION
(SELECT friendID
FROM friends
WHERE userID = 1)
If you want to return usernames too, you can do your JOINs inside the subqueries:
(SELECT f.userID, u.username
FROM friends f
JOIN users u
ON u.userID = f.userID
WHERE f.friendID = 1)
UNION
(SELECT f.friendID, u.username
FROM friends f
JOIN users u
ON u.userID = f.friendID
WHERE f.userID = 1)

Categories