Users History and Users saved database schema design - php

I want to store into database the visited users and favourite users (when a user clicks on hearth icon). So, I could create 1 table, users_activities like so:
Users_activities:
id_users (pk)
id_users2 (pk)
activity (varchar or enum, it'll contain "history", "favourite") (pk)
created (datetime)
For the history.php or favourites.php pages, I'll select all, where id_users = X and activity = "history/favourite", join users table. For insert and update, I have a composite primary key, users, users2 and activity. If I'll find a users X, users2 Y and activity Z, update the row..else insert.
Otherwise, I could create 2 separated table, users_history and users_favourite, like so:
Users_history
id_users (pk)
id_users2 (pk)
created
users_favourite
id_users (pk)
id_users2 (pk)
created
it's a simple design and SQL is tiny simple than first form. Which is better? I use php and mysql.

"History" sounds like a log of things. "Favorites" sounds like a current set of values. They have two different sets of usages and properties; do not put them in the same table.

Related

Simple MYSQL data query?

Just a really simple question. In my SQL database I have a column named "friend_count" in table "users" to record all friends the logged in user has. This works with UserID numbers and I am trying to figure out how to record them all. Here's my example:
USER #29 becomes friends with USER #422
In the user database under USER #29's info in the column "friend_count" there will then be the number "422", if he then becomes friends with USER #500, it will show "422, 500" and so on... If he deletes one, that particular number is removed from the box. The script will then search these numbers through the user database to show a list of the people you are friends with.
How can I do this? Any ideas? Thanks!
Any time you have a delimited list of values in a column it's almost always a sign that the data model is incorrect. (Actually, I can't think of an exception to this, but I'll stick with "almost always" just to be safe.)
In this case you have two types of entities:
User
Friendship
A friendship, though not a physical object, is a conceptual entity in and of itself. It connects two users and can add more information related to the friendship itself but not necessarily to the two users.
So you might have tables like this:
User
--------
ID
Name
etc.
Friendship
--------
ID
OriginatingUser
AcceptingUser
BecameFriendsOn
etc.
So OriginatingUser might be the user who sent the friend request, and AcceptingUser might be the user who accepted it. BecameFriendsOn is the date it was accepted. You'd probably want to have statuses and other dates to keep track of pending requests, denied requests, etc. But all of this information is related to the friendship, not necessarily to the users.
The concept you're looking to understand here is called a Foreign Key. The OriginatingUser and AcceptingUser columns are the same data type as the ID column on the User table. You would create the Friendship table such that those columns are foreign keys to the User table, this enforces the integrity of the data so that you can't create a Friendship record without two valid and existing User records.
Then to get the list of friends, you'd join the tables in a query. Perhaps something like this:
SELECT
User.Name
FROM
Friendship
INNER JOIN User ON Friendship.AcceptingUser = User.ID
WHERE
Friendship.OriginatingUser = ?
When supplied with the ID of the originating user, this would get all of the names of users to whom that user sent a friend request. You can further build on the query to also get users who sent this same user a friend request, and so on. By making use of the key foreign key relationships between tables which represent different types of entities in the system, you can construct very robust queries to view that data in lots of different ways.
You are describing a relationship between two entities so you can create a table to store the details of that relationship.
Suppose that you have your user table with a userid column and other columns. You can then create a friends table with two columns that are both foreign keys to the user table.
friends = (user, friend)
Thus, for each friend that user #29 gets you need to add a row into the friends table. For example:
USER
ID NAME ...
29 Sam
30 Henry
32 Jane
Friends
user friend
29 30
29 32
Sam is friends with both Jane and Henry but Jane and Henry are not friends.
I would create a table "friendship" with two cols "user" and "friend", then you start adding pairs of user/friend ids
users table:
id, username, whatever else
friends table:
relationship_id, user_id, user_friend_id
example query to get a list of IDs that belong to the users friends:
SELECT f.user_friend_id FROM users u
LEFT JOIN friends f ON f.user_id = u.id
WHERE u.id = {$user_id}
A very simple approach, assuming that if UserA becomes friends with UserB , then UserB also becomes friends with UserA.
Usually, Comma Separated Lists are not recommended, as they will become a pain when the list is very large. A simpler approach will be, make a table friends with columns user_id and friend_id Where user_id and friend_id are the respective UserIDs .
Now when you want to add a friend to someone's list, use the following :
INSERT INTO users (user_id,friend_id) VALUES(UserA,UserB),(UserB,UserA)
Now when you execute the above query, you will have 2 new rows in your friends table :
user_id friend_id
UserA UserB
UserB UserA
When you want to get the list of a user's friends, use :
SELECT friend_id FROM friends WHERE user_id=(Your user's ID)
This will return a row one by one, and hence will give you all the IDs of friends of a particular user.
Now when you want to delete a friend, use :
DELETE FROM friends WHERE (user_id,friend_id) IN ((user_id,friend_id),(friend_id,user_id))
This removes both the rows from the table, which means that the relationship between UserA and UserB is deleted, and neither of them is friend of each other.

mysql- Database schema of messaging application with different group

I know how to make a simple messaging schema for one to one user messaging ( all user come from same table) but my problem is that I have multiple Table with different type of users which have their primary keys now when a user from one table want to send a message to a user from another table then what should be schema for this application,
Let I have these three tables with different type of users-
TableA- id | Name |...
TableB- id | Name | ...
TableC- id | Name | ...
Now a user from TableA want to send a message to a user from TableB or TableC then what should be database schema for messaging app (all three tables can have different user with same primary key i.e id)
Storing the same types of data with slightly differing properties is antithetical to databases. You can make it work by pointing to Table.ID within your application, but it's not pretty and not best practice.
What you're looking for is a single users table with one or more flags or references (more columns/fields in the table) indicating what details are different for each user. If you need multiple user groups, you should simply have groups table.
eg.:
# users table
CREATE TABLE users (
user_id INT,
user_name VARCHAR(32),
group_id INT,
talk_outside_group BOOL
);
# groups table
CREATE TABLE user_groups (
group_id INT,
group_name VARCHAR(32),
);
INSERT INTO user_groups SET group_id = 1, group_name = 'PHBs';
INSERT INTO user_groups SET group_id = 2, group_name = 'HR';
INSERT INTO users SET user_id = 1, group_id = 1, user_name = 'Alice';
INSERT INTO users SET user_id = 2, group_id = 1, user_name = 'Bob';
INSERT INTO users SET user_id = 3, group_id = 2, user_name = 'Carol';
INSERT INTO users SET user_id = 4, group_id = 2, user_name = 'Dave';
In this example, Alice and Bob are PHBs and can barely work their keyboards.
Carol and Dave are HR drones and have boring conversations ;)
When and whether users of separate groups can talk to each other could be indicated by a flag in either table (depending on how granular you need the privilege control... in this example, the talk_outside_group field) and should be handled in the application layer.
Your users shouldn't be in different tables.
If you want some users to have privileges then do a table "privileges" and link it to "users" with a table "user_privilege" which would contain "id_user" and "id_privilege".
If you really want to do what you are doing, then you'll have to add a field "table_name" in the message table to be able to know from where the user is coming.

How to link a row of MySQL database table to another row in another table

I know it makes little sense... and i'm new to using MySQL...
What i'm trying to do here is, link one tables row to another tables row...
for an example there are two tables..
one table is for user registration and same table is used for login as well...
and the next table is for user posts.. like status updates and all...
here is how i want it...
user_log_info:-
id ( primary )
firstname
lastname
username
email
password
posts:-
id ( primary )
userposts
posted_by
date_post
so as you can see, i want the user_log_info tables username to be automatically copied to posts posted_by row... And i have no idea how i can archive this...
You haven't given nearly enough information to give a full answer, but I'll do my best with what you've given.
Tables
+-----------------+ +-----------------+
| users_log_info | | posts |
+-----------------+ +-----------------+
| int ID (primary)| | int ID (primary)|
+-----------------+ | int posted_by |
+-----------------+
(I left off fields that are irrelevant to what you seem to want to do, I'm just simplifying it)
posted_by is an unofficial foreign key, or referencing the primary key of another table.
To insert, what you can do is along the lines of this:
INSERT INTO posts(...., posted_by) VALUES (...., user.ID)
Where .... is referencing all of your other information to insert
Then, to find information on someone who posted something:
SELECT * FROM users_log_info WHERE ID = Post.posted_by
Or if you want to find all posts by a user:
SELECT * FROM posts WHERE posted_by = user.ID
So, if Bob, who is User ID 3 wants to post "Hi", you might be able to do:
INSERT INTO posts(content, posted_by) VALUES('Hi', bob.ID)
And then when you are outputting the post you might do this:
post = (however you choose the post to put on the page)
userPosted = SELECT * FROM users_log_info WHERE ID = post.posted_by
print post.content + " posted by: " userPosted.Name
Essentially, the field "posted_by" is, to "posts" an arbitrary number, but you know that it links to, or references, a user. It does that by referencing "ID", which is the primary key of users_log_info, so that when you want to get information from users_log_info, is all you need to do is select the entry which has the ID that corresponds to "posted_by". I do recommend naming it something like posterID, however, for easier identification.

MySQL table to hold pages that a user likes

How would I set up a table for topics that a user likes? I have a topics tables and a user table (more actually but simplified for a post on here). There is an ever increasing number of topics as they are user generated, how could I allow users to like pages? Would i put the topic's id in the user table or the user's id in the topics table or a create a new likes table? The issue I see is that the number of topics could (potentially) be very large. What could I use to create a system that allows a relationship between a users id and the topics id?
What you could possibly do is a "many to many" table structure
A unique auto incremented id - UINT (10) AUTO_INCREMENT
A feild containing the user id - UINT (10) (or what ever matches your main user_id field)
A field containing the "liked" topic id - UINT (10) (or what ever matches your main topic_id field)
Both user_id and topic_id fields would need to be unique together. That means that there can only be once row for a specific like per user. This makes sure (on the database side), that a user will not be allowed to like a topic more than once.
Getting a users liked topics would look like this -
SELECT * FROM user_likes` WHERE `user_id`=USER_ID
Getting the users per like would look like this -
SELECT * FROM user_likesWHEREtopic_id`=TOPIC_ID
As others have said in their answers and also #trevor in the comments below -
Don't forget to add an index on the userid to support retrieval of user liked topics and a separate index on topic is to support the topics per user query - without these, the queries will get slower as more data is added over time.
One way to do it is to create a new table UserLikedTopics or something similar, in which you have two columns, one to keep the UserId and one to keep the TopicId. For each new topic a user "Likes", you add a new row to the table with the UserId and the TopicId. That way it is easy to keep track of which users likes which topics.
To get whoch topics a certain user like, you simply join the UserLikedTopics with your topics table, and you have a list of all topics a certain user like. You could also make it the other way around and join it on the User table, to get a list of the users that like a certain topic.
You will need a 'likes' table. Something like:
CREATE TABLE `users_likes` (
`user_id` INT(10) UNSIGNED NOT NULL,
`topic_id` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`user_id`, `topic_id`),
INDEX `topic_id` (`topic_id`)
)
Create a separate likes table since it's a separate entity,
link the likes table with users & topics table with userid & topicsid as foreign keys in likes table..
It would be good to have a structure like this, later if you dont even want a feature likes, can just remove it without affecting other tables...

System for keeping track of user favorites

On my website, I have a table movies and a table users
I'm trying to have an "Add to favs" button that a user can click, which will add that movie to his favorites (ajax / javascript not necessary at the moment, just php).
So what's the simplest way I could do something like that? I've thought about this but I can't seem to find a solution (all I think of is way too complicated, and in my opinion not possible).
What's your thoughts?
I don't need a ready-made script, just an idea that could get me working (although if you have an example of such script, I'd be happy to look at it).
Thanks!
This is a many-to-many relationship. A user can favorite many movies, and a movie can be favored by many users. In an RDBMS, you represent a many-to-many relationship with a third table. I call this an intersection table but it goes by other names too.
Create a table with two columns. The columns are both foreign keys, referencing movies and users, respectively.
CREATE TABLE Favorites (
user_id INT NOT NULL,
movie_id INT NOT NULL,
PRIMARY KEY (user_id, movie_id),
FOREIGN KEY (user_id) REFERENCES Users(user_id),
FOREIGN KEY (movie_id) REFERENCES Movies(movie_id)
);
When a user chooses to favorite a movie:
INSERT INTO Favorites (user_id, movie_id) VALUES (?, ?)
When a user decides they don't like a movie any longer, delete the corresponding row:
DELETE FROM Favorites WHERE (user_id, movie_id) = (?, ?)
To get the set of movies favored by a given user:
SELECT movie_id FROM Favorites WHERE user_id = ?
To get the set of users who favor a given movie:
SELECT user_id FROM Favorites WHERE movie_id = ?
Regarding one of your comments:
You shouldn't make the "Add to favorite" a link. Indexers like Google will follow links, and then before you know it, every user has favorited every movie.
The general best practice is that read-only operations can be GET requests, while operations that write to the database can be POST requests. This means that you need to use a <form> element to submit POST requests, not an <a href="..."> element.
Add a third table:
CREATE TABLE user_favorites (
user_id INT NOT NULL,
movie_id INT NOT NULL,
PRIMARY KEY (user_id, movie_id),
FOREIGN KEY user_id REFERENCES users (user_id),
FOREIGN KEY movie_id REFERENCES movies (movie_id)
)
This is called an intersection table or join table, as it joins rows in the users table to rows in the movies table (as you see, each column is a foreign key). It is also defines a many-to-many relationship, because one user can like many movies and one movie can be liked by many users.
When you go to add a favorite movie for a user, all you have to do is insert a row in this table with the ID of the user and the ID of the movie:
INSERT INTO user_favorites(user_id, movie_id) VALUES([user ID], [movie ID])
To see what movies a user has favorited:
SELECT movie_id FROM user_favorites WHERE user_id = [user ID]
You will need to create a new table:
user_favorite_movies
--------------------
ID (primary key)
userID (foreign key)
movieID (foreign key)
date
Then when the user clicks the 'Add Favorite' button, you just insert a new row into user_favorite_movies with the users ID from the user table, the movie id from the movie table, and the date it was added (good for sorting later).
Hope this helps!
Best,
-Eric
You could create a table favourites with three columns, id, mid and uid. To add a favourite:
INSERT INTO favourites (mid, uid) VALUES (3, 5)
To search for favourites of one user:
SELECT * FROM favourites WHERE uid = 7
To search for people who favourited one movie:
SELECT * FROM favourites WHERE mid = 9
So far as I can see, you'll still need to use JavaScript or Ajax to do the post, unless you want to refresh the page every time thet mark/unmark a favorite, and also to add/remove the new favorite indicator in place at the same time.
Or am I missing something?

Categories