Reputation:
I'm trying to build a database that will store information on movies.
Title
Plot
Genre
Rating
Director
The only thing that is bothering me is that most films don't just have one genre and I'm struggling to figure out how to store this on a MySQL Database. At first I was thinking that I'll just have one table and store all the genres in one column, separating them by a comma and when I want to retrieve them separate them using PHP, but I'm not sure this is the best way as I think I would have trouble sorting and searching for a specific genre e.g. Horror when the collumn contains 'Horror, Thriller, Action'.
Upvotes: 6
Views: 10525
Reputation: 697
I would eliminate the arbitrary surrogate keys movieID
and genreID
as a way to remove unnecessary overhead for the relational database. Since title
and genre
are natural unique keys, we should use them and not ask the database to maintain the uniqueness of extra, meaningless keys and tables (the genres
table in the referenced answer). This should improve the speed and performance for large relational databases and is good practice.
tablename: movies
primary key: title
title, plot, rating, director
> sample data:
> Titanic Bollywood 10 James Cameron
tablename: moviegenres
primary key: title, genre
title, genre
> sample data:
> Titanic Thriller
> Titanic Romance
This also makes queries a lot easier for both the user and the machine since you don't have to join an extra table to decode the genres by the arbitrary UID.
Upvotes: 5
Reputation: 90
it's a bit late, but I made a simple code from the top comment code above
select movieid, title, plot, rating, director, group_concat(genre)
from movies
natural join moviegenres
natural join genres;
Upvotes: 0
Reputation: 1421
What you are looking to model here is called a "many-to-many" relationship, and is very common when modelling "real world" categorisations.
There are many descriptions out there of how to work with such relationships including:
Do not be tempted to skip the extra intersection table by storing multiple genres in one field for each film (a comma separated list for instance). This is a very common "anti pattern" that will cause you problems, maybe not today, maybe not tomorrow, but eventually. I recommend anyone working with database design give Bill Karwin's "SQL Antipatterns" (http://pragprog.com/book/bksqla/sql-antipatterns) a read. It is written in a way that should be accessible to a relative beginner, but contains much that those of us who should know better need reminding of from time to time (many-to-many relations, the list-in-a-field solution/problem, and what you should do instead, are one of the first things the book covers).
Upvotes: 10
Reputation: 7123
I would suggest you should follow the following structure:
tablename: movies
movieid, title, plot, rating, director
> sample data:
>
> 1 titanic Bollywood 10 James Cameron
tablename: genres
genreid, genre
> sample data:
> 1 Horror
> 2 Thriller
> 3 Action
> 4 Love
tablename: moviegenres
moviegenresid, movieid, genreid
> sample data:
> 1 1 2
> 2 1 4
And the query is:
select m.*,group_concat(g.genre)
from movies m inner join moviegenres mg
on m.movieid=mg.movieid
inner join genres g
on g.genreid=mg.genreid
group by m.movieid
;
See the fiddle
Upvotes: 12