Normalization for music/concerts database - mysql

My understanding with normalization after reading my book and going through a few youtube tutorials is that one of the important things is to not have repeating values. More specifically the primary key (ID) should not repeat.
So if I am working with some Tables in a Music/Concert database, then the following would be bad:
**CREATE TABLE Artists**
ArtistID INT *PRIMARY KEY*
ArtistName VARCHAR(30)
Albums
^Having Albums in the Artists table would be bad as there is One
Artist for Many Albums. Therefore the ArtistID would have to show up
in multiple rows [once for each album by the artist]
Question: Should a table like this have a foreign key that ties to another Table? The related table I would think about is obviously Albums.
Albums would have columns like:
CREATE Table Albums (
Album_ID INT NOT NULL AUTO_INCREMENT,
Album_Name VARCHAR(30),
Artist VARCHAR(30),
Release_Date DATETIME,
Genre or GenreID,
Primary Key (Album_ID) );
Question: But albums have songs. However I can't have Album ID as the Primary Key and then have all the songs with the repeating Primary Key of Album ID for each can I? Should I therefore keep the attribute 'Songs' out of the Album table?

Question: Should a table like this have a foreign key that ties to another Table? The related table I would think about is obviously Albums.
If the relationship between artist and album is one to many... (if the rules are that an "artist" can have zero, one or more "albums", and an "album" belongs to exactly one "artist")
We would implement that relationship by storing artist_id as a foreign key column on the album table.
Something like this:
artists:
artist
------
id 'PK'
name varchar
albums:
album
-----
id 'PK'
artist_id 'FK ref artist.id'
title
year
artwork
By storing a value in the artist_id column of album, that is a reference to a row in the artist table.
artist:
id name
---- --------
1 Kansas
2 Styx
album:
id artist_id name year
---- --------- -------------------- ----
432 1 Leftoverture 1976
435 1 Point of Know Return 1977
438 1 Monolith 1979
561 2 Grand Illusion 1977
Question: But albums have songs. ... Should I therefore keep the attribute 'Songs' out of the Album table?
Yes. If it's a one to many relationship between album and song, then store the album_id on the song table.
Like this:
songs:
song
----
id 'PK'
album_id 'FK ref album.id'
song_title
lyrics
song
id album_id song_title
---- -------- ------------------------
6777 435 Dust In The Wind
6801 438 People of the South Wind
5555 561 Come Sail Away
From a row in the song table, we can use the value stored in the album_id column to find the related album.
From a row in the album table, we can use the value stored in the artist_id column to find the related row in artist.
These examples are based on the simplistic one-to-many relationships that are described.
It's important that we get these rules for the relationships between the entities into a reasonable representation. We need to know if a relationship is one-to-many or many-to-many.

you need to read Database Systemsby Connolly & Begg - who will define clearly what makes data relational and how to define entities, and when to normalise data, but yes in answer to your question around whether you should use a foreign key in the songs table to link the artist to the song - remember this table will hold songs which means naturally the artist id would appear multiple times, and so on and so on research entities properly that will help.

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.

Inputting multiple values into a relational database field

I am creating a database application for a restaurant stock management system. I currently have two database tables, one for the ingredients, and one for each dish.
Database tables and relationships
Each ingredient has a unique ID which is the PK of the table. And the 'ingredients' field in the DISH table is a foreign key linking to ingredient_ID. Each dish will obviously have many ingredients, but the ingredients can also belong to multiple dishes. I have read elsewhere about creating another table called ingredient_dish for example, but I'm not sure I fully understand how this works. Could somebody either point me in the right direction or attempt to explain please, and what sort of columns would I have in this joining table for the above tables?
Thanks a lot.
Since you have a Many-to-Many relationship between Ingredients and Dishes, you may want Ingredient_Dish to be a Cross-Reference table.
Its fields would include ingredient_id, a foreign key to the Ingredients table, and dish_id, a foreign key to the Dish table. Set the primary key of this new table to the combination of both fields. A creation command might look like the following, tailor it to suit:
CREATE TABLE Ingredient_Dish (
ingredient_id INT NOT NULL,
dish_id INT NOT NULL,
CONSTRAINT PK_Ingredients_by_dish PRIMARY KEY (ingredient_id, dish_id))
ALTER TABLE Ingredient_Dish
ADD CONSTRAINT FK_Ingredients FOREIGN KEY (ingredient_id) REFERENCES Ingredient (ingredient_id )
ALTER TABLE Ingredient_Dish
ADD CONSTRAINT FK_Dishess FOREIGN KEY (dish_id) REFERENCES Dish (dish_id)
Many-to-many relationships are best done with such an intermediate (or "bridge") table. The bridge table basically consists of the primary keys of the other tables to form a "bigger" foreign key, which allows you to implement a many-to-many relationship by providing primary key combinations.
Your use case (simplified) would necessitate tables like these:
dishes:
dish_id | other_columns
-------------------------
1 | ...
2 | ...
3 | ...
ingredients:
ingredient_id | other_columns
-------------------------------
1 | ...
2 | ...
3 | ...
dishes_ingredients_bridge:
dish_id | ingredient_id
-------------------------
1 | 1
1 | 2
2 | 2
2 | 3
3 | 3
This means you have 3 dishes and 3 ingredients, where
dish 1 consists of ingredients 1 and 2
dish 2 consists of ingredients 2 and 3
dish 3 consists only of ingredient 3
ingredient 1 is used only in dish 1
ingredient 2 is used in dishes 1 and 2
ingredient 3 is used in dishes 2 and 3
Also, make sure, the combinations in your bridge are unique (create a multi-column unique key). Omitting this usually doesn't result in big problems, but in some edge cases your application could behave in an undefined or unexpected way.
Now you can query (for example) all ingredients of dish 1 like this:
SELECT i.*
FROM ingredients as i
LEFT JOIN dishes_ingredients_bridge dib
ON dib.ingredient_id = dib.ingredient_id
LEFT JOIN dishes as d
ON d.dish_id = dib.dish_id
"Connecting" a dish to an ingredient means adding a row to the bridge. "Disconnecting" a dish from an ingredient means deleting such rows, respectively.
Hope this helps.
You are basically describing a bridge table. It's the only way to describe a many-to-many relationship without concatenating values (which is a very nasty can of worms). I suggest you read this further:
http://www.kimballgroup.com/2012/02/design-tip-142-building-bridges/
Hope it helps.

Multiple Column Confusion

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.

Multiple foreign keys to different tables on a single id

I'm trying to create a rather complicated relationship between the tweets and its author. In my system, I have 3 sources which can be related to a tweet (teams, players and persons). The issue is that instead of having a teamId, personId and teamId in each tweet and only one of them is not null. I've come up with below solution with a relational table called created. However the issue is that I'm not sure it is possible to create a foreign key from the sourceId to all 3 ids in Teams, Players and Persons tables? What can I do in order to create the right table structure for this type of system?
To explain the Created table further it contains free columns:
id = primary key and auto_increment
sourceType = enum can be (persons, teams or Players). By doing this i know whether it is a person, team or player
sourceId = is the id of the particular person, team or player.
Players
id
name
image
twitter_user
teamId
Teams
id
name
twitter_user
Persons
id
name
image
twitter_user
teamId
Tweet
id
created
text
createdId
Created
id
sourcetype
sourceId

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.