Home > Enterprise >  SQL DB Model: Multiple artists on single song
SQL DB Model: Multiple artists on single song

Time:09-19

I am wondering about the best way to model this for when there are multiple artists for a given song.

id   song_title           artist
=================================================
1    Battle Sirens        Knife Party, Tom Morello
2    Internet Friends     Knife Party
3    Satisfy              Nero

Where ultimately I want it to work like this:

id   song_title           artist
=================================================
1    Battle Sirens        [1,2]

With an artist table like this:

id   artist_name        
===================
1    Knife Party       
2    Tom Morello
3    Nero

It makes the most sense to me to have each artist field as a string containing an array of artist ids: "[1,2]", but this doesn't seem like the right way to do it in just SQL.

The only other things I can think to do are:

  • Have a new table for combinations of artists with an arbitrary identifier.
  • Have an 'assoc' table where there are two records for the same song id when there are two artists behind it.

CodePudding user response:

Creating an association table is the normal way of handling a m:m relationship

CodePudding user response:

The best way is use DB normal form with many-to-many relation. This demand 3 tables: songs, artists and song_artists:

CREATE TABLE songs (
  id int primary key, 
  song_title varchar(64)
);

INSERT INTO songs 
VALUES 
  (1, 'Battle Sirens'), 
  (2, 'Internet Friends'), 
  (3, 'Satisfy');

CREATE TABLE artists (
  id int primary key, 
  artist_name varchar(64)
);

INSERT INTO artists 
VALUES 
  (1, 'Knife Party'), 
  (2, 'Tom Morello'), 
  (3, 'Nero');

CREATE TABLE song_artists (
  song_id int references songs(id), 
  artist_id int references artists(id),
  primary key (song_id, artist_id)
);

INSERT INTO song_artists 
VALUES 
  (1, 1), 
  (1, 2), 
  (2, 2), 
  (3, 3);

SELECT 
  song_title, 
  GROUP_CONCAT(artist_name) AS artists 
FROM 
  songs 
  JOIN song_artists ON song_artists.song_id = songs.id 
  JOIN artists ON artists.id = song_artists.artist_id 
GROUP BY 
  songs.id, 
  song_title;

When you can use next query to fetch related data:

SELECT 
  song_title, 
  GROUP_CONCAT(artist_name) AS artists 
FROM 
  songs 
  JOIN song_artists ON song_artists.song_id = songs.id 
  JOIN artists ON artists.id = song_artists.artist_id 
GROUP BY 
  songs.id, 
  song_title;

online sql editor

Result:

 ================== ========================= 
| song_title       | artists                 |
 ================== ========================= 
| Battle Sirens    | Tom Morello,Knife Party |
 ------------------ ------------------------- 
| Internet Friends | Tom Morello             |
 ------------------ ------------------------- 
| Satisfy          | Nero                    |
 ------------------ ------------------------- 
  • Related