Suppose I wanted to have a table of users for people who collected various rare video games. Further suppose I made a model for a list of video games that can be created and saved by those users. How would I save the list in the database.
For example, my thoughts are there would be a cell in the user table called game_list which is a comma separated list of game('s). The games being a separate table with static game data and statistics which the users can pick from to create their rare game list.
Is this the best way? BTW, I am using rails, in case of specific solutions. I know this question is rather general, but I have a hard time phrasing the question to google and this site to get the answer I am looking for. I'm quite new to web development (SQL and HTML5 parts mostly), but not programming (been programming for a long time).
Thank you!
This is a many-to-many relationship. One usually models this with a table for user information, a table for game information, and a table for each user-game relation:
create table user(
user_id int primary key,
user_name varchar(255));
create table game(
game_id int primary key,
game_name varchar(255));
create table user_game(
user_id int not null references user(user_id),
game_id int not null references video(video_id));
insert into user values (1, "ed"), (2, "bob");
insert into game values (1, "pacman"), (2, "poker");
insert into user_game values (1, 1), (1, 2), (2, 2);
select user_name, game_name
from user
natural join user_game
natural join game;
http://sqlfiddle.com/#!2/6b637/1
A thing you could do is make a form, so the user can choose which games they wanna store. Then you take the games the user have selected and make a array.
Foreach game in the array you do a query to the table in your database which contains the game data, and you get the id and make a array. Then you use var game_list = serialize($array) in php (http://php.net/manual/en/function.serialize.php), for example and update the user table with the variable you got from serialize().
If you then wanna get the data and make it to a array again you should use var game_list = unserialize($row).
Related
Is it possible to create a new column in a SQL query results? I'm thinking of expanding my movie database to handle multiple users. I have a table with the basic movie details such as title type plot rating year released and have a table with a list of movie Ids and user ids for the movies that a user has marked as watched. I would like to generate a list for a user and to show if it has been watched or not by said user.
Ex
The matrix watched
The matrix 2
Or
The matrix 2 un-watched
Or would it be a better idea to create a table that has a list of movie ids nada user idea and a status column?
So, you have users and movies. A user could've watched many movies. A single movie could've been watched by many users. This means it's a many-to-many relationship.
That's a standard problem. The solution:
movies table - movie id, title, type etc. - you got that already
users_to_movies - user id, movie id, status (or e.g. date watched, NULL if not watched), any other data if need be
users - user id, name, last name, e-mail - whatever you need there.
The primary key in users_to_movies is a compound key, consisting of two columns: (user_id, movie_id).
The table users_to_movies is an association table. This is the "bridge" between two tables that are in a many-to-many relationship.
Example:
User with id 5 watched Matrix 2 (id 12 in movies table) on 4th Sep 6pm. So you INSERT INTO users_to_movies VALUES(5, 12, '2014-04-09'). If you want to store the information that user id 2 hasn't watched Matrix 2, you insert (2, 12, NULL).
You should add a new table
This is a Many-to-Many table relationship
this table should contain userID and movieID
I think you dont need a status column (if watched, there is a line / if not, there is nothing)
I have a poll which has an undefined number of options (it can have only 2 options, but it can also have 10 or 20 or more options to choose from). I need to store the current vote count in MySQL table. I can't think of a centralized way of storing them except:
Create a field vote_count and store a serialized array of voting options mapped to counts.
When new vote data comes in this field is read, unserialized, appropriate values are incremented, then field is written to. This needs 2 queries and there might be 5 or more votes incoming per second.
So I need a way to store voting counts for an unknown number of voting options and be able to quickly access it (I need up to date counts for every option displayed on the voting page) and quickly update it (when new votes come in). It has to be within MySQL table. There is no "upper" limit for the number of voting options.
The normative pattern for handling multi-valued attributes, or repeating values, is to add a second table.
Consider a purchase order that can have more than one line item on it. We represent the line items in a child table, with a foreign key to the parent in the purchase order table:
CREATE TABLE `purchase_order` (id int not null, foo varchar(200), ... );
CREATE TABLE `line_item` (id int not null, order_id int not null, ... );
ALTER TABLE `line_item` ADD FOREIGN KEY (order_id) REFERENCES order(id) ;
INSERT INTO purchase_order (id, foo) VALUES (101, 'bar');
INSERT INTO purchase_order (id, order_id) VALUES (783, 101);
INSERT INTO purchase_order (id, order_id) VALUES (784, 101);
INSERT INTO purchase_order (id, order_id) VALUES (785, 101);
We can get a count of the line items associated with a purchase order, like this:
SELECT COUNT(1)
FROM line_item
WHERE order_id = 101;
Or, we can get a count of line items for every purchase order, like this:
SELECT o.id, COUNT(l.id) AS count_line_itesm
FROM purchase_order o
LEFT
JOIN line_item l
ON l.order_id = o.id
GROUP BY o.id
In your case, what are the entities you need to represent (person, place, thing, concept or event; which can be uniquely identified and you need to store information about.
I'm having difficulty conceptualizing what entities it is you are need to represent.
poll -
poll_question - a single question on a given poll
poll_question_answer - a possible answer to a question to a given poll question
voter -
ballot - associated with one voter and one poll (?)
vote - the answer given to a particular poll question
Good database design comes from an understanding of the entities and the relationships, and developing a suitable model.
Can't you just have one table of questions, and another table of possible answers (multiple rows per question, as many as you want). Then either store the counts on the table of answers, or (better) have another table of actual entered answers (this way you can log the details of the person doing the answers, and easily use SUM / COUNT to work out how many votes each option has).
I'm designing a database that contains a list of recipes and their ingredients and now i'm in the processing of linking the individual ingredients to their respective recipes. However, i'm having trouble deciding on the best course of action on how to populate the associative entity table.
I have my 3 tables,
CREATE TABLE Ingredient
(
ingredientID int PRIMARY KEY AUTO_INCREMENT,
ING VARCHAR(100)
);
CREATE TABLE Recipe
(
recipeID int PRIMARY KEY AUTO_INCREMENT,
recipeTitle VARCHAR(200),
prepText VARCHAR(10000),
cuisineType VARCHAR(100)
);
CREATE TABLE recipeIng
(
recipeID int,
ingredientID int,
PRIMARY KEY (recipeID, ingredientID)
);
The Ingredient table is populated from an XML file containing 200+ individual ingredients, which each auto assigned a different ID starting at 1.
The Recipe table is populated by another XML file, containing the recipe title, preparation method and cuisine type.
The recipeIng table is what i'm having trouble with, I assume it will have to be populated by hand. i.e manually matching all the ingredients to their recipes. Like this:
INSERT INTO recipeIng
VALUES(1, 1);
INSERT INTO recipeIng
VALUES(1, 2);
INSERT INTO recipeIng
VALUES(1,3);
INSERT INTO recipeIng
VALUES(1, 4);
With '1' being the id of the first recipe and '1', '2' etc being the individual ingredient ID.
However i'm unsure if this is the best approach for the populating the table and any advice would be helpful.
Note: When combined with the in-use method of populating this query works fine.
SELECT r.recipeTitle
FROM Recipe r
INNER JOIN recipeIng e ON e.recipeID=r.recipeID
INNER JOIN Ingredient i ON i.ingredientID = e.ingredientID
WHERE 'brown sugar' IN (i.ING);
By viewing your last questions, I think this approach is at least better than having a comma-separated list of ids in one of the tables. Having a list of comma-separated values would f.e. limit you in the number of connections, depending on the configuration you have for the field storing the list of values.
The way, you showed here, is the way I design mn-relations in relational databases, too. This is also what you'd get using tools like MySQL Designer, so I think it's the best way to store a many-to-many relation.
I haven't really found much documentation around this excepted by this article, which is linked at the Wikipedia page for many-to-many relations: http://www.tomjewett.com/dbdesign/dbdesign.php?page=manymany.php
I am going through this exact situation with my website, but I'm dealing with testimonials instead of recipes. The only thing I have come up with so far that may help you is to do tons of inserts at once. For example, if most of your recipes call for flour, then you could a select insert statement that would insert 'flour' into recipeIng for multiple recipeIDs.
Good luck!
I have two tables. "users" and "movies". Users table consists of "id"(Auto increment), "name" and "password" columns. There are 2 usernames stored right now. In movies table there are 'title' and 'year' columns. The PHP script allows each user to watch and add new movies to their list. How do I link or make the parent-child relationship or whatever is needed to make it happen in MySQL? Oh, and I also use Adminer. Right now when I log in one user I still see the same movies that I've added with the other user.
If you are stuck with using just two tables as stated in a comment, you have to redesign the Movies table to include a column UserID which identifies which user created that entry. Then you can filter the data so that a user only sees information about the movies they added to the list.
This isn't a good design — the answer by Jeremy Smyth suggesting an extra table to relate movies to users is much more sensible, but you've indicated that isn't allowed. The reason it isn't a good design is that you're going to end up with lots of rows indicating that the same movie was released in the same year, each row entered by a different user, so there is unnecessary repetition. There's also more chance for error; you'll get entries for 'Gone With The Wind' 1938, and 'Gone With The Wind' 1939, and 'Gone With The Wind' 1940 when there should only be one year (1939, as it happens).
Can you please be more specific about what I have to do ...
In the two-tables-only system, you would create the Movies table like this:
CREATE TABLE Movies
(
Title VARCHAR(32) NOT NULL,
Year INTEGER NOT NULL,
UserID INTEGER NOT NULL REFERENCES Users(ID),
PRIMARY KEY(Title, Year, UserID)
);
When you insert a record into this table, you record the ID of the user who did the insertion, so you can query who created which movie records.
If you are actually going to reference this table from elsewhere in the database, you might well add an ID column here, but if there are more tables, then you'd drop the UserID column from this table and create a relationship table:
CREATE TABLE Movies
(
ID INTEGER AUTOINCREMENT PRIMARY KEY,
Title VARCHAR(32) NOT NULL,
Year INTEGER NOT NULL,
UNIQUE(Title, Year)
);
CREATE TABLE Users_Movies
(
MovieID INTEGER NOT NULL REFERENCES Movies(ID),
UserID INTEGER NOT NULL REFERENCES Users(ID),
PRIMARY KEY(MovieID, UserID)
);
Now you can have one record for 'Gone With The Wind' 1939, which might have ID number 207, and twenty different people might list MovieID 207 as one of their movies with 20 simple records in the Users_Movies table.
You will need to create a "many-to-many" relationship between your two tables.
To do this:
First, create an ID column in the Movies table to uniquely identify each one
Then, create another table called user_movies (or "watched" or something useful), that contains the user ID, the movie ID, and any other information you wish to add such as date watched or rating (number of "stars") etc.
Then, whenever a user watches a movie, add a record to the user_movies table to mark the fact that they've done it.
It should be many-to-many, because each user can watch several movies, but each movie can be watched by several users. A "parent-child" relationship isn't appropriate in this case, being a one-to-many relationship.
I'm looking forward to a logic to store friends list in a database. I'mthinking of adding things in an array with userids
example: user a's array in friends table would contain userid arrays of friends like 1,2,4,6,77,44 etc
I want to know whether this will be an efficient way of doing this. If not, what logic should be ideally implemented for large community?
You likely need a separate many-to-many join table. To achieve this, if both the user and their friends reside in the same user table. The table could look like this:
user_id - id of user the friend lookup is being done for, is foreign key to user_id field in user table
friend_id - id of friend associated with user, also is a foreign key to user_id field in user table
You would have a compound primary key across both fields, ensuring that each user_id to friend_id combination is unique.
This would be sample CREATE TABLE statement:
CREATE TABLE `friends` (
`user_id` INT(11) NOT NULL,
`friend_id` INT(11) NOT NULL,
PRIMARY KEY (`user_id`, `friend_id`)
)
ENGINE = INNODB;
And sample data may look like this:
INSERT INTO `friends` (`user_id`, `friend_id`)
VALUES
(1, 2), (1, 3), (1, 4), (2, 1), (2, 10), (4, 1), (4, 20);
Then say you wanted to do a lookup of all the user table data for the friends associated with a particular user (i.e. the logged in user). You could query that data like this:
SELECT users.*
FROM users
INNER JOIN friends ON users.user_id = friends.friend_id
WHERE friends.user_id = [The ID of current user]
No, no, no!
Don't store multiple values in one db field. It will bring you very much problems.
You could use a stucture like this for instance
friends (user_id, user_id)
which indicates 2 friends.