Multiple Column Confusion - mysql

I am developing a web based music application. I get struck into a confusion related to MySQL columns.
Problem is like this:
I have album table:
album_id
album_name
album_year
Now the problem is: an album can contains multiple tracks (identified by track_id). Now how to store multiple track id's in album table?
I am novice to MySQL.

You have to create another table, lets name it album_has_tracks.
It has following structure:
album_id track_id
1 1
1 2
1 3
2 4
2 5
2 6
That is named relations and that is one of the point, that MySQL is named relational database. Both of the album_id and track_id are foreign keys and represent columns with their ids. After that, to get the data of the tracks, you have to use JOIN. So that are the basic you have to read about.
I would suggest you to read some basic about relational databases, for example here.

You need to find some tutorials on relational database design.
You wouldn't store the tracks in the album table, you would create an album tracks table with, for example, track_id, album_id, track_name
The album_id in the tracks table would be set as a foreign key linked to the album table and you would set its value in the track entries to the matching album_id from the album table.

Related

What's wrong in this normalized table?

I have the following album table:
album_id(PK)
album_name
artist_name
year
songs
My candidate keys are {id} and {album_name, artist_name}.
Now I am going to normalize the table till 3NF, and I would like to know the reason behind the data of artist_name column being redundant.
1NF
Goal: columns should be atomic.
Result:
album:
album_id(PK)
album_name
artist_name
year
song:
song_id(PK)
album_id(FK)
song_name
2NF
Goal: No partial functional dependencies of non-prime attributes (columns that don't exist in any candidate key) on candidate keys.
Solution: I couldn't find any partial functional dependencies.
3NF
Goal: No transitive functional dependencies of non-prime attributes on candidate keys.
Solution: I couldn't find any transitive dependencies.
Problem
Although the tables above seem normalized, there's the following problem: the data in the artist_name column is redundant. An artist with multiple albums will have their name stored multiple times, which we are against.
What am I missing?
i would create a table called artist and in there store the artist id and name and in the album table have a reference to that using a foreign key constraint. So where you would have artist name in album this would change to artist id. It wouldn't be a issue if you just have the name like you do now but if you have additional data that you would need to store for a artist then you would have to create the table anyway which would break the current design as you would have the name in the album table and the rest of the information in the artist table.
The main goal of normalization is to reduce redundancy. With the artist name being in the album table if you ever needed the name of a artist and additional artist info then you would have to include the album table and the artist table which wouldn't make sense and you wouldn't have any other columns besides name to link the tables together or duplicate the data in two places both the album and artist table which would violate the 1st normal form.
Also, with the name being in the album table your data would be split across two tables. The artists name isn't really a dependency on album but on the artist entity. This violates values stored in a column should be of the same domain principle of the 1st normal form.

how to make a relationship table between 3 table (2 to 1) in SQL

lets say we have 3 table in our database
tables:
table books:
book_id
book_title
...
table magazines:
magazine_id
magazine_title
...
and genres:
genre_id:
genre_name
and now we say want to know what book has what genre and what magazine has what genre, this is the way i know for two table
relation tables:
table book_genres:
genre_id
book_id
table magazine_genre:
genre_id
magazine_id
in this way we have to create several separate table for joining the books, magazine and maybe more tables. and i been told that always have 2 id column in join tables.
but i'm wondering about if i could do something like this
the table that not working!
table title_genres:
genre_id
book_id
magazine_id
...
this is more simple but i get an error when i insert a book genres that says magazine_id can't be empty NULL because its primary key.
its gonna be save me for creating a lot of tables. like if i decide to have a category table then i have to join books and magazine separately.
and my question: is the 2 column thing is a good practice or there is a better way for this?
You use bridge tables to represent m:n relationships. If a book can have many genres and a magazine can have many genres, then you need bridge tables like the book_genres table you are showing.
And if books are very different from magazines in your database, then yes, have separate tables for books and magazines.
This leads to two bridge tables, just as you describe and I see nothing wrong with this.
Your idea to have one bridge table is generally possible, but doesn't solve any problem.
But well, let's see how we would construct such a multi bridge table. First of all you'll want a check constraint ensuring that always exactly one of the columns book_id and magazine_id is filled. Then you want a unique constraint on COALESCE(book_id, magazine_id), genre_id. This would usually be done with a function index, which MySQL doesn't support as far as I know. I suppose though, that you could create a generated column which you can index in MySQL.
And then you want to read the relations as quick as possible. With a bridge table like book_genres you have one row per book and genre and an index to get the relation as quick as possible. With a multi bridge table like title_genres you don't. You have one table containing relations you are interested in and others you are not interested in. You'd want a partial index like
create unique index idx on title_genres (book_id, genre_id) where book_id is not null;
but MySQL doesn't support partial indexes. You could
create unique index idx on title_genres (book_id, genre_id);
which leads to a larger index, but serves the purpose. You'd do the same with
create unique index idx2 on title_genres (magazine_id, genre_id);
And now, with all this work, what have you gained? Your database has become way more complicated than with the simple book_genres and magazine_genres tables. Keep it simple. Use these two tables instead of the multi bridge monster :-)
You can absolutely store the records this way if you have a category field that has information such as (books, magazines etc). So, in other words your table is vertically partitioned by category field but logically it’s a single table.
Only drawback I can see is if this table grows fast then query performance would be a problem because (a) the table will be huge so it will consume more memory even if you are only looking for specific categories and not all of them (b) you always have to use inline sub query since your category filter have to applied every time for every join and when you use inline queries for joins the database would not be able to make use of indexes will be affect the performance of the queries.
Note : You would not be able to store the records in any other way. For example even if a magazine and a book have same genre you have to have them in separate rows and not the same row because if you do that your model will get into other kind of troubles.

How to handle data storage for each user MySQL

suppose I have a table with users in my website. Now if I want to make a system where users can upload a single image each, it would be something like this:
But if I want to make a system where users can upload an unlimited number of images, how would I achieve that? Would I need to create a column for each image uploaded per user? But in that case, wouldn't be fields unused? Example:
Also, if I wanted to make albumns for the photos how would I handle that? Thanks!
The best way of handling this would be to have a separate table for images, but with a userID which is a foreign key for your user table.
Assuming no two users would use the same image (which would be a different situation),
You have your user table just as you have (the first one), but with only the id and user.
Your second table would look something like this, where imageID is the primary key, and UserID is a foreign key for ID off of your user table
imageID UserID
1 1
2 1
3 1
4 2
5 2
If you want albums, you could just create another table with albumID as a primary key, and imageID as a foreign key to this image table. You can also include UserID on that table and create a composite primary key if you want a many-to-many relationship. This way albums are still associated with users, but you could have images appear in multiple albums

Foreign Key in SQL pivot table - database design

I am using DBDesigner 4 for designing my database relations.
I have a users table and a recipes table. One user can own many recipes but one recipe cannot be owned by many users. This relationship is shown by the user_recipes relation in the picture. (A one-to-many relationship from users to recipes).
However, recipes can be liked by users. Many users can like many recipes. This is a many-to-many relationship between users and recipes and the pivot table for this is users_like_recipes.
But when I create this pivot table, I only need the users_id and recipes_id column. The recipes_users_id column is getting added on its own and I am not able to remove it. It says the third column has come from another Relation which is defined in the model. I guess its the user_recipes relation.
When I remove the user_recipes relation, I get the pivot table like I want to.
But I need the user_recipes relation too!
Please. Any help would be appreciated.
I would suggest removing user_id as a primary key from from the recipes table. Currently the combination if id and user_id provides identification for your recipes table. In this situation multiple user_id's can create the same recipe id because the combination has to be unique. user_id can just be a normal column in your table. If you REALLY want to, you can make an alternate key on (id, user_id) but you do not need it because the id is unique.

MySQL combine two indexes into one

I was wondering if there is some way to combine two indexes into third to make sort of serial number... For example:
If I want to create music database
I would start with table artists with
-artist_name
-artist_id (Primary key)
-....
Then table albums with
-album_name
-album_id (P.k.)
-...
And then table songs with
-song_title
-song_id
Let's say artist would be X with artist_id - 12345
Then album Y with album_id - 678
And I want song_id to be 12345.678.xxx (dots only for visualization of the idea, length of artist_id and album_id would be constant)
My question is. Is something like possible?
Because I have a feeling that this would perform much more better search through database.
Not only that in my song_id I have full information of artist and album (I don't need to use foreign keys than), it should speed up any query about songs from the same album or other albums of the same artist. All information in one index and it needs only some kind of extraction.
Or maybe its just mine minimal knowledge about MySQL? :)
Keep artist_id and album_id as separate columns in the songs table and include proper foreign key relationships and indexes. This will give you the best combination of data integrity and query performance.