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...
Related
I have a table called user_thoughts. The table has many columns, one of them being favourited_by.
A thought may be favourited by many different users, but I don't want to create a new row stating that this thought id has been favourited by this user.
I would rather have it that it stores multiple username's in one field. So favourited_by for example can hold data like this:
Alice, Fred, Freddy, Conor ....
All in one single row. I have tried messing around with the data types on phpMyAdmin but cannot figure out how the field can hold multiple data.
What you're asking is the wrong way to do this. You should not serialize the favorites data into a text field for either the user table or the thought table. This destroys the whole purpose of using a relational database like MySQL.
The right way to do this: create a cross-reference table between the user table and the thought table. This utilizes a many-to-many table to store a list of favorites using the primary keys of a thought row and a user row.
Your new favorite table:
CREATE TABLE IF NOT EXISTS `favorite` (
`id` int NOT NULL AUTO_INCREMENT,
`user_id` int NOT NULL,
`thought_id` int NOT NULL,
PRIMARY KEY (`id`)
);
What this does is take the id from the user table and store it in favorite.user_id, then stores the id from the thought table in favorite.thought_id.
To add a new favorite for the user with the id of 123, for the thought with id 456:
INSERT INTO favorite (user_id, thought_id) VALUES ('123', '456');
Get the users that have marked the thought with id 456 as their favorite (using a JOIN):
SELECT u.* FROM favorite AS f
JOIN user AS u ON u.id = f.user_id
WHERE f.thought_id = 456;
And similar to the last query, get the favorite thoughts for the user with id 123:
SELECT t.* FROM favorite AS f
JOIN thought AS t ON t.id = f.thought_id
WHERE f.user_id = 123;
The ideal way to handle this is to map it to another table, however you can just store it as json.
MySQL 5.7 even includes JSON as a data type allowing easier filtering and manipulation.
https://dev.mysql.com/doc/refman/5.7/en/json.html
You can put json into any text field however if you don't need to search it, etc.
I have been working on the header recently. Now I'm end up to create some likes button like Facebook do.
I'm following the PHPacademy on Youtube. The one who's called Alex is really awesome to share what his idea is.
The problem is, I can't show the user name and the product name which to be liked
This is my query:
function plus_the_like($meal_id) {
$meal_id = (int)$meal_id;
$user_name = mysql_query("SELECT `fullname` FROM `users` WHERE `user_id` = (".$_SESSION['user_id'].")");
mysql_query("UPDATE `meal` SET `likes_meter` = `likes_meter` + 1 WHERE `meal_id` = $meal_id");
mysql_query("INSERT INTO `likes` (`user_id`,`user_name`, `meal_id`) VALUES (".$_SESSION['user_id'].", $user_name, $meal_id)") or die(mysql_error());
}
I know what I am doing wrong just on my query, but ahh... When I'm using the SQL in MySQL all works so well:
SELECT `fullname` FROM `users` WHERE `user_id` = 1
And that query can show me what is the username with the user_id 1
I hope that I can put that username from users table into likes table
Here is what you should be doing.
You have a users table with the following information
id - this is a unique ID of the user, this should be marked as a primary key. Auto incrementing.
Keep whatever else information you want on the user, possibly name, email, etc.
You have an articles table (or whatever your likes are based off of.
id - this is a unique ID of the article, this should be marked as a primary key. Auto incrementing.
Store whatever information you want on your articles, or your items in a store or whatever it is you want to "like".
You have a likes table.
id - this is a unique ID of the like, this should be marked as a primary key. Auto incrementing.
user_id - this is a unique ID of your user that clicked the like button, should be marked as a foreign key.
article_id - this is a unique ID of your article that was "liked", should be marked as a foreign key.
With this, whenever a user "likes" an article, you would have a query like
INSERT INTO likes (user_id, article_id) VALUES (:userID, :articleID);
and to count the number of likes on a given article, you would do something like
SELECT count (user_id) FROM likes WHERE article_id = :articleID;
This will allow you to track how many likes for each article, as well as what each user liked. Potentially, you could eventually suggest things to users based on what they have liked. Though, that is a lot more work to do.
This is a very basic version of what you are attempting to accomplish. As people in the comments have said, look into properly sanitizing your database input. If nothing else, at least change to my_sqli_* if you do not have PDO access. PDO is the suggested way to go though, if you are not going to use a framework that gives you all of this.
Just to save anyone reading this time and trouble, DO NOT use this method to store surveys. As pointed out in the answer, this is incredibly poor programming (not to mention dangerous to kitties)
Forgive me if this question is somewhat convoluted. I'm working on building a program that allows users to create surveys and post them for users to take.
Long story short, I have a table that looks like this:
**survey_info**
id bigint(20) Auto_increment Primary Key
title varchar(255)
category bigint(20)
active tinyint(1)
length int(11)
redirect text
now, when a survey is created, a new table is also created that is custom built to hold hte input for that survey. The naming schema I'm using for these new tables is survey_{survey_id}
What I'm hoping to do is in the list of surveys, put the number of responses to a survey to the right of it.
Alright, now my actual question is this, is there a way to retrieve the number of rows in the collection table (survey_id) within the same query I'm using to gather the list of available surveys? I realize that I can do this easily by just using a second query for each survey and grab it's rowcount, but my fear is that the larger the number of surveys the user has, the more time-consuming this process will become. So is there any way to do something like:
SELECT s.id AS id, s.title AS title, c.title AS ctitle, s.active AS active, s.length AS length, s.redirect AS redirect, n.num FROM survey_info s, survey_category c, (SELECT COUNT(*) AS num FROM survey_s.id) n WHERE s.category = c.id;
I just don't know for sure how to use the s.id as part of the other table's name (or if it can even be done)
Any help, or even a point in the right direction would be appreciated!
You need to use one table for all the surveys.
Add newly created id not as a table name but as a survey id in that table.
You create a relational model that will store all surveys options in one table. This is a sample design:
survey
------
id PK
title
surveyOption
--------------
id PK
survey_id FK
option
surveyResponse
--------------
id PK
surveyOptionId FK
response
Ok so a user comes to my web application and gets points and the like for activity, sort of similar (but not as complex) as this site. They can vote, comment, submit, favorite, vote for comments, write description etc and so on.
At the moment I store a user action in a table against a date like so
Table user_actions
action_id - PK AI int
user_id - PK int
action_type - varchar(20)
date_of_action - datetime
So for example if a user comes along and leaves a comment or votes on a comment, then the rows would look something like this
action_id = 4
user_id = 25
action_type = 'new_comment'
date_of_action = '2011-11-21 14:12:12';
action_id = 4
user_id = 25
action_type = 'user_comment_vote'
date_of_action = '2011-12-01 14:12:12';
All good I hear you say, but not quite, remember that these rows would reside in the user_actions table which is a different table to the ones in which the comments and user comment votes are stored in.
So how do I know what comment links to what row in the user_actions?
Well I could just link to the unique comment_id in the comments table to a new column, called target_primary_key in the user_actions table?
Nope. Can't do that because the action could equally have been a user_comment_vote which has a composite key (double key)?
So the thought I am left with is, do I just add the primary keys in a column and comma deliminate them and let PHP parse it out?
So taking the example above, the lines below show how I would store the target primary keys
new_comment
target_primary_keys - 12 // the unique comment_id from the comments table
user_comment_vote
target_primary_keys - 22,12 // the unique comment_id from the comments table
So basically a user makes an action, the user_actions is updated and so is the specific table, but how do I link the two while still allowing for multiple keys?
Has anyone had experience with storing user activity before?
Any thoughts are welcome, no wrong answers here.
You do not need a user actions table.
To calculate the "score" you can run one query over multiple tables and multiply the count of matching comments, ratings etc. with a multiplier (25 points for a comment, 10 for a rating, ...).
To speed up your page you can store the total score in an extra table or the user table and refresh the total score with triggers if the score changes.
If you want to display the number of ratings or comments you can do the same.
Get the details from the existing tables and store the total number of comments and ratings in an extra table.
The simplest answer is to just use another table, which can contain multiple matches for any key and allow great indexing options:
create table users_to_actions (
user_id int(20) not null,
action_id int(20) not null,
action_type varchar(25) not null,
category_or_other_criteria ...
);
create index(uta_u_a) on users_to_actions(user_id, action_id);
To expand on this a bit, you would then select items by joining them with this table:
select
*
from
users_to_actions as uta join comments as c using(action_id)
where
uta.action_type = 'comment' and user_id = 25
order by
c.post_date
Or maybe a nested query depending on your needs:
select * from users where user_id in(
select
user_id
from
users_to_actions
where
uta.action_type = 'comment'
);
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?