How to handle a bidirectional many-to-many relationship with PHP - php

I am trying to setup a bidirectional many-to-many relationship using the same table data, namely User, I also have a link table named Userusers which joins the one user with another user, but I am not sure how to handle the bidirectional side, because the result of my code only shows one direction.
--Table User:
create table User (
UserID int auto_increment not null,
UserFirstName varchar(30) not null,
UserSurname varchar(30) not null,
UserTel char(10),
UserCell char(10),
UserEmail varchar(50) not null,
UserPassword varchar(50) not null,
UserImage varchar(50),
UserAddress1 varchar(50),
UserAddress2 varchar(50),
UserTown/City varchar(50),
UserProvince varchar(50),
UserCountry varchar(50),
UserPostalCode varchar(50),
Primary key(UserID)
)
--Table Userusers:
create table UserUsers (
UserID int not null,
FriendID int not null,
primary key(UserID, FriendID),
foreign key(UserID) references User(UserID),
foreign key(FriendID) references User(UserID)
)
PHP code:
$sql="SELECT * FROM User u INNER JOIN UserUsers uu ON uu.UserID = u.UserID INNER JOIN User f ON f.UserID = uu.FriendID WHERE uu.UserID = " . $_SESSION['userID'];

Actually, no, your tables do show bidirectional relationships.
Consider your table UsersUsers
The column userID represents the person who is FRIENDS WITH friendID.
Say user 1 wants to be friends with user 2
Our UsersUsers table will look like:
UserID | FriendID
1 2
Sure, we see that there is now a relationship between User 1 and 2, but we also see that User1 has initiated the friendship, showing the direction from 1 -> 2
Now when User2 wants to accept the friendship, we can insert another record into the table, making it:
UserID | FriendID
1 2
2 1
There's definitely some better meta data you can add to the relationship table to understand more about the relationship created, but the UserID field should be considered the owner, or sender, and the FriendID should be considered the receiver.
So - you already have most of the work cut out for you, now all you have to do is create your queries to act upon this bidirectional relationship.
Getting all confirmed friends for User1:
We will assume $the_logged_in_user_id = 1
SELECT * from Users U JOIN UsersUsers F ON U.UserID = F.UserID WHERE F.FriendID = '$the_logged_in_user_id'
That will show all the confirmed friendships for $the_logged_in_user_id, assuming this is what you're going for.

Related

Mysql using LIKE to match phone number

I have an app where user phone book uploaded on server same like whatsapp,telegram,facebook etc.
User imported phone book structure look like this
Table Name: PhoneBook
id user_id first_name mobile(Varchar(20))
1 100 John +91981000000
2 100 Tom 91981000001
3 100 Ron 9810-000-02
4 100 Mat 91981000003
5 100 Miley 981000004
Table Name: Registered_User (Main Table For Existing Users)
ID Name Phone (Varchar(20))
1 Sam 09811111111
2 Abby 919811000000
3 Ben +19854646464
4 Tom +91981000001
5 Ron 981000002
6 Sam 981111145
So When user wants to see how many friends of my existing contact on the app then first i need to grab all contacts of user with his/her user_id (100 in above example) from PhoneBook table then i need to check if anyone from user_id = 100 phonebook's exist on Table Registered_User and if yes then returns all of Registered_User table column
Here is my query
SELECT * FROM Registered_User as MA
Join PhoneBook as N ON N.mobile Like '%' MA.Phone
where N.user_id = 100
Table Schema
CREATE TABLE `Phonebook` (
`id` int NOT NULL AUTO_INCREMENT,
`user_id` int NOT NULL,
`first_name` varchar(250) NOT NULL,
`mobile` varchar(250) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3520 DEFAULT CHARSET=latin1
The query above returns zero result even when the user 100(user id) has few users in Registered_User table. Can you help me to fix this query. I am not expert in creating query.
Table data should return result Tom 981000001 and Ron 981000002. Please let me know if i missed something and is this the best way to get the get the existing users of the app?

Why this mySQL LEFT JOIN won't work? Can it be the WHERE clause?

I'm making a PHP script to show to which user roles the current user belongs.
The data is in mySQL and what I want is to show all available roles and of all of them, show where the user belongs to.
this is my roles table
CREATE TABLE roles(
roleID int unsigned not null auto_increment primary key,
nombreRol char(50) not null
)
The roles here are:
registered
pending
student
former-student
and this is the table that connects the usuarios table with the roles table
CREATE TABLE rolesUsuarios (
rolesUsuariosID int unsigned not null auto_increment primary key,
userID int not null,
nombreRol char(50) not null
)
I'm trying to create a LEFT JOIN like this:
SELECT
roles.nombreRol,
rolesUsuarios.userID
FROM roles
LEFT JOIN rolesUsuarios
ON roles.nombreRol = rolesUsuarios.nombreRol
WHERE rolesUsuarios.userID = 183
(I'm not concerned with security at the moment, just checking that the query is working)
In the example, the user 183 has the roles registered and student.
The intended result should be like this:
nombreRol -------- userID
registered ------- 183
pending ---------- NULL
student ---------- 183
former-student --- NULL
But I get this result instead:
nombreRol -------- userID
registered ------- 183
student ---------- 183
How may I change the join? (I've followed the example here and it does work there, and I think that I've followed the logic of the query correctly)
Your where clause is turning the left join into an inner join. Add it to the ON clause of the join instead.
Try this:
SELECT
roles.nombreRol,
rolesUsuarios.userID
FROM roles
LEFT JOIN rolesUsuarios
ON roles.nombreRol = rolesUsuarios.nombreRol
AND rolesUsuarios.userID = 183
I thinhk the result is correct. If you want to get your expected result, your WHERE condition should like that:
WHERE rolesUsuarios.userID = 183 or rolesUsuarios.userID is NULL

How to check if values from the table 1 are used in table 2?

I have two tables employees and departments.
Departments:
create table dept (
id INT NOT NULL AUTO_INCREMENT,
dept_name VARCHAR(50) NOT NULL,
PRIMARY KEY (id)
);
Employees:
create table department_master (
id INT NOT NULL AUTO_INCREMENT,
dept_id INT NOT NULL,
emp_name VARCHAR(100) NOT NULL,
PRIMARY KEY (id)
);
I want to prevent departments being deleted from the UI if they are assigned to one of the employees in employee table. Left join is giving me duplicate values.
How do I see if the departments are being used in the employees table.
If you want to prevent a department from being deleted, you can simply add a foreign constraint to the table department_master for dept_id column.
create table department_master (
id INT NOT NULL AUTO_INCREMENT,
dept_id INT NOT NULL,
emp_name VARCHAR(100) NOT NULL,
PRIMARY KEY (id),
constraint con_dm foreign key dept_id references dept( id )
);
It's default behavior is ON DELETE RESTRICT which means that if there is atleast one row present in the department_master for a given dept_id, it can't be deleted from dept table.
If you want to fetch, the department that don't have any employee record, you can use NOT EXISTS:
select *
from dept d
where not exists (
select 1
from department_master m
where d.id = m.dept_id
);
I believe you want a count of the number of employees grouped by the department, like so:
SELECT count(*) as employees, d.dept_name FROM dept AS d LEFT JOIN department_master AS e ON e.dept_id = d.id group by e.dept_id

subscription algorithm that scales

Web application PHP,Mysql. Users can write articles. How to build algorithm that allows users to subscribe (follow) to other users articles and then see list of last articles added by subscribed users? Algorithm must scale, so that one user can subscribe to 10 000 users and 10 000 users can subscribe to one user and all parts works quick - when new article added and when users looks for last articles from subscribed users.
create table `user`(
`id` INT(10) PRIMARY KEY NOT NULL AUTO_INCREMENT
);
create table `subscribes_to` (
`subscriber_user_id` INT(10) NOT NULL,
`subscribed_to_user_id` INT(10) NOT NULL, # Receiver of the subscription
PRIMARY KEY(`subscribe_user_id`, `subribed_to_user_id`),
KEY `subscriber(`subscribe_user_id`),
KEY `subscribed(`subscribed_to_user_id`);
);
# Users subscribed to role 100
SELECT distinct u.* FROM user u
JOIN subscribes_to st ON st.subscriber_user_id = u.id
WHERE
st.subscribded_to_user_id = 100;
# User 100's subsriptions
SELECT distinct u.* FROM user u
JOIN subscribes_to st ON st.subscribded_to_user_id = u.id
WHERE
st.subscriber_user_id = 100;
Additional Schema to show relationship with articles:
article (
id int(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255),
body TEXT,
date_created DATETIME,
date_updated DATETIME,
author_user_id int(10)
);
# Create new article
INSERT INTO `article` VALUES (NULL, "Hello", "This is the body", NOW(), NOW(), 1);
# Find the last 10 articles posted that user 15 suscribes to
# the author of
SELECT a.* FROM article a
JOIN user ON u.id = a.author_user_id
JOIN subscribes_to st ON st.subscribed_to_user_id = u.id
WHERE st.subscriber_user_id = 15 ORDER BY a.date_created DESC LIMIT 10;

PHP: Idea for friend-system?

I need help on making a friend-system.
I am thinking how to make so both users can see that they are friends together.
Should i just make a user1 field and user2 field, and then when displaying him/her´s friends, it should select where user1 ='$id' OR user2 = '$id' ?
Or should i make two rows each time people are being friends?
Smart way and example would be appreciated. Thank you.
I am storing in mysql database.
My thoughts is exactly in how should i list that who is friend with who. Lets say i use method 1) with user1 and user2 column, then i should have WHERE user1 or user2 is $id (users id) but can this work properly?
I just tried this and it shows the userid for user2 in user1´s friendslist,
but in user2´s friendslist it just shows his own userid and not the user1s..
On a big projects with sharding you should always replicate data for each user.
For not so big project it's okay to keep one table with "initiator" and "accepter" fields for user_id. Don't forget to add indexes and "status" field for friendship
I'm assuming you're storing them in a database. A simple way would be to have a new table, lets call it "friendships" with two columns, user_1, user_2. If two users are friends, they should have a row in this table. This is an extremely simple way of implementing this, but it should work.
SELECT users.name, fr.name
FROM users, friends, users AS fr
WHERE users.user_id = ?
AND users.user_id = friends.user_id1
AND friends.user_id2 = fr.user_id
UNION
SELECT users.name, fr.name
FROM users, friends, users AS fr
WHERE users.user_id = ?
AND users.user_id = friends.user_id2
AND friends.user_id1 = fr.user_id
This will allow you check against an intermediary table for your many-to-many relationship and not have to duplicate (inverse) rows.
CREATE TABLE `users` (
`user_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
PRIMARY KEY (`user_id`),
);
CREATE TABLE `friends` (
`user_id1` bigint(20) unsigned NOT NULL,
`user_id2` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`user_id1`,`user_id2`)
);
Some good answers here, If I had to do this I would do it one way, this way you can determine if the friendship has been confirmed and also ensure the friendship is mutual, so for example
Lets assume status has two values
0 = Unconfirmed
10 = Confirmed
Using simple tables with status for acceptance levels
CREATE TABLE `users` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
PRIMARY KEY (`user_id`),
);
CREATE TABLE `friend` (
`user_id` bigint(20) unsigned NOT NULL,
`friend_id` bigint(20) unsigned NOT NULL,
`status` int(11) unsigned NOT NULL,
PRIMARY KEY (`user_id`,`friend_id`)
);
INSERT INTO `users` (`id`, `name`) VALUES
(1, 'Jack'),
(2, 'John');
Jack would like to be friends with John, so you would create a relationship between the two only one way:
INSERT INTO `friend` (`user_id`, `friend_id`, `status`) VALUES (1, 2, 0);
Now you can query the database to find Jacks friends or Jacks requests and Johns friends or Johns requests using simple queries
To find Jacks unconfirmed friends you would use something like
SELECT users.* FROM users JOIN friend ON users.id = friend.user_id WHERE friend.friend_id = 1 AND friend.status = 0
To find Jacks confirmed friends you would use something like
SELECT users.* FROM users JOIN friend ON users.id = friend.user_id WHERE friend.friend_id = 1 AND friend.status = 10
To find Jacks any friend requests you would use something like
SELECT users.* FROM users JOIN friend ON users.id = friend.user_id WHERE friend.friend_id = 1
When someone makes a confirmation of friendship you would perform 2 queries, one for updating the record and one as a reverse confirmation
UPDATE friend SET status = 10 WHERE user_id = 1 AND friend_id = 2;
INSERT INTO `friend` (`user_id`, `friend_id`, `status`) VALUES (2, 1, 10);
On a different note, I would also use a Graph database for complex relationship queries whilst maintaining a firm copy in the MySQL database
Graph teaser for friends of friends to build relationships
MATCH (Person { id: 1 })-[:knows*2..2]->(friend_of_friend) WHERE NOT (Person)-[:knows]->(friend_of_friend) AND NOT friend_of_friend.id = 1 RETURN friend_of_friend.id, friend_of_friend.name LIMIT 10

Categories