Linking columns in different tables in MySql / parent-child relation - mysql

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.

Related

Mysql Storing multi values in a column

I have a tables called userAccounts userProfiles and usersearches.
Each userAccount may have multiply Profiles. Each user may have many searches.
I have the db set up working with this. However in each search there may be several user profiles.
Ie, each user account may have a profile for each member of their family.
They then want to search and include all or some of their family members in their search. The way i would kinda like it to work is have a column in user searches called profiles and basically have a list of profileID that are included in that search. (But as far as i know, you can't do this in sql)
The only way i can think i can do this is have 10 columns called profile1, profile2 ... profile10 and place each profileid into the column and 0 or null in the unused space. (but this is clearly messy )
Creating columns of the form name1...nameN is a clear violation of the Zero, One or Infinity Rule of database normalization. Arbitrarily having ten of them is not the right approach, that's an assumption that will prove to be either wildly generous or too constrained most of the time. Since you're using a relational database, try and store your data relationally.
Consider the schema:
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT NOT NULL,
name VARCHAR(255),
UNIQUE KEY index_on_name (name)
);
CREATE TABLE profiles (
id INT PRIMARY KEY AUTO_INCREMENT NOT NULL,
user_id INT NOT NULL,
name VARCHAR(255),
email VARCHAR(255),
KEY index_on_user_id (user_id)
);
With that you can create zero or more profile records as required. You can also add or remove fields from the profile records without impacting the main user records.
If you ever want to search for all profiles associated with a user:
SELECT ... FROM profiles
LEFT JOIN users ON
users.id=profiles.user_id
WHERE users.name=?
Using a simple JOIN or subquery you can easily exercise this relationship.

Get a list in MySQL

I'm creating a website and users can add friends. I want them to be able to see their personal friends on a page.
For exemple:
John add user Tim and Bill.
When John goes on his friends list page, I want him to be able to see that he has Tim and Bill. How do I do that? Is that even possible? Do I need more than one table? If so, does every user has to have his own friendsList table?
Yes this is possible, you do this by querying the information from the database, the answer for if you need multiple tables etc all depends on your current table structure but at the very least you need to have some way of referencing that a Person 'John' has friends, wether thats just a 'friendID' in the same 'Person' table, or another means of doing so. then it is just a matter of querying the data correctly to return what you want and bind to the websites fields :D
One way of defining the structure is the following:
Person
PersonId
Name
<other person fields>
Relationship
RelationshipId
Name --> allow to define multiple relation types like Friendship, Follows etc.
Relationship
RelationshipId
Person1Id --> FK to Person
Person2Id --> FK to Person
RelationshipTypeId --> FK Relationship
Basically, you use an n:n between Persons (anyone can have any number of friends) and also allow for other types of relationships.
Assuming you already have a table of users, one approach would be to create a "friends" table which relates users to other users.
CREATE TABLE friends (
`user_id` INT NOT NULL,
`friend_id` INT NOT NULL
);
Both user_id and friend_id would have foreign key constraints on your existing users table (so that you guarantee an id must exist in your user table in order for it to exist in the friends table as either a user_id or friend_id).
You can then link your user table on users.id = friends.friend_id to get the friend's info.
Here is a SQL Fiddle Demo showing how this works.
You should consider using an ON DELETE CASCADE constraint on the friends table, so that if a user is deleted from the user table, the associated records in the friends table are also deleted.

Deciding database table architecture

I'm very new to Databases and looking forward to develop an application with some advanced functionality.
Here I'm going to have a table with users just like the following one.
So, in the sports column, value will be the sports the user plays. They will be some ids from the records of sports table.
So my problem is how to store those multiple values in the same row same column ?
Thanks
PS: Please note that I'm a beginner...
The proper way to do this would be to maintain three different tables.
User: id, name, age
Sport: id, name
UserSport: user_id, sport_id
The UserSport table references the primary key (id) of both tables (User and Sport) and contains a separate entry for each sport the user participates in.
The primary key of UserSport should then be a composite key of both user_id and sport_id. This allows you to have multiple rows for each user and multiple rows for each sport, but a unique combination of both the user and sport.

MySQL: M:N Table Linking Two Tables

I'm getting ready to populate a couple of tables in a movie database I have created. The Movies table has already been created. It looks like this:
movieid INT NOT NULL PRIMARY KEY
title VARCHAR(50)
link VARCHAR(100)
release_date VARCHAR(10)
It should perhaps be noted that I'm using MySQL-python and Scrapy to populate this data in the MySQL database, but perhaps that doesn't matter.
I have created three additional tables which have not yet been populated: Producers, Actors and Directors. Each of these looks like the other in that there exists id, name and movie title. So Actors looks like:
actorid INT NOT NULL PRIMARY KEY
actor VARCHAR(40)
title VARCHAR(50) <<<<------ This is the movie title from the Movies tables
Now, I would like to create a table called Movie To Actor which holds the movieid from the Movie table and the actorid from the Actor table and not have the title column existing in the Actors table.
I figure there are two ways to do this:
First Way:
Get all of the data into the Actors table with title acting as a foreign key and to THEN create the Movie To Actor table, adding the appropriate ids where movies.title is equal to Actors.title and to then drop the title column from Actors.
Second way:
Do this as I am populating the data. First create the Movie to Actor table, set up key constraints and set this to auto update as the data is added to Actors table. I would prefer this as it makes things significantly easier and I think is stylistically better. Was hoping someone could instruct me on how I would go about doing this. I think I can figure out how to extrapolate instructions in MySQL into MySQL-python, but would need help on how to do the former.
A couple points first off:
Unless you're manually populating the actorid and movieid fields in the actors and movies tables you should have an auto_increment on those columns.
If you're using movies.title to link to anything else, you should add a unique index to that column in the movies table.
You should ultimately drop the title column from the actors table. Otherwise you'll either have multiple rows for the same actor name (redundant) or only one movie per actor (unrealistic).
For the first method you mentioned, you actually can first create the movie_actor table and then populate the existing data:
INSERT INTO movie_actor (movieid, actorid) SELECT movieid, actorid FROM movies INNER JOIN actors ON actors.title=movies.title;
For the second, you can use a trigger:
delimiter //
CREATE TRIGGER add_actor
AFTER INSERT ON actors
FOR EACH ROW BEGIN
SET #movieid = (SELECT movieid FROM movies WHERE title=NEW.title);
IF #movieid IS NOT NULL THEN
INSERT INTO movie_actor (movieid, actorid) VALUES (#movieid, NEW.actorid);
END IF;
END;
//
delimiter ;
I'd suggest option 1 followed by having whatever form you're using to populate these tables to populate the movie_actor table independently (e.g. after adding an actor, you can set whatever movies he/she was in, merely adding a mapping to the movie_actor table). Then if you want to get a list of movies for an actor you can just
SELECT title FROM movie_actor
INNER JOIN movies ON movies.movieid=movie_actor.movieid
WHERE actorid=????

creating a new mysql table with a primary auto incrementing id that is linked to another table?

I want two tables to share a primary auto incrementing id, is this possible? how do i do this? is their anything i need to consider?
the reasons i am doing this, is because it is a better solution than adding groups column to the users table, and also better than creating a completly seperate groups table, because if they share a primary key, i can use the existing posts table for both groups and users. instead of having to create a two distinct posts tables, (group_posts table for group posts. and a user_posts table for user posts.)
existing users table is
id(primary, ai)
username
password
email
my groups table that i want to link to my users table with a shared ai primary key
id(primary, ai, linked to users table id)
group_name
created_by
creation_date
etc.
You should make you schema clearer by doing the following:
Create a table (e.g. people)
id, primary key, auto-increment
type, tells you if it's a user or a group
Make users and groups primary keys foreign keys on people
Insert records in people
Obtain the ID that was assigned using LAST_INSERT_ID()
Insert in users or groups appropriately, using the ID obtained above
Then you'd reference "people", and not "users" or "groups" in your posts table and so on.
Conceptually, thinking of it in an OO way, it means users and groups both extend people.