2

I am building a web app that displays charting records/albums from the 50s and 60s.

Currently I have something like this (lots of irrelevant stuff removed):

group_performance_role

The table named "group" was once modeled as a "person" table, a "person_group" joining table and a "group" table. The problem with this is that I can't have the foreign key 'group_performance_role.group_id' reference BOTH the "person" and "group" tables.

I decided to keep that structure but require every "person" automatically be a "group" of 1; however, this creates a naming ambiguity and means that the table holds more than one thing - sometimes a single Artist ("John Lennon") and sometimes a Group ("The Beatles").

I need to find a way to link an Artist (which could be a single person or a group of people) with a performance, while avoiding bad practices like a table that holds more than one "type" of thing.

I have searched the web, but found little in the way of relevant answers. Any help/advice/suggestions much appreciated!!

EDIT: The "role" table is a lookup table for roles that people/groups can perform on performances. Examples: "Artist", "Composer", "Orchestra Conductor" etc etc

Alex McMillan
  • 17,096
  • 12
  • 55
  • 88

4 Answers4

3

Consider using inheritance to model the various kinds or artists:

(BTW, your Group_Member table allows groups-in-groups. I'm guessing this is not what you wanted.)

enter image description here

However, this ignores any differences roles might have depending on the artist type. For example, it makes little sense for a whole group to be a "Conductor". If enforcing these kinds of constraints is important, you could take a "brute force" approach and simply separate the person-specific from group-specific roles:

enter image description here

(BTW, if you wanted to prevent overlap between names of group-specific and person-specific roles, you'd have to put both role tables in an inheritance hierarchy. Not shown here.)

Of course this still doesn't honor the cardinality of certain roles. For example, only one person (per performance) can be the "Conductor". To solve that, you'd have to extend the model even further:

enter image description here

And possibly similar thing would have to be done for the groups.

To get all the people involved in a given performance (say 27) through any of these three kinds of roles, you'd need a query similar to this:

SELECT *
FROM Person
WHERE person_id IN (

    SELECT person_id
    FROM Group_Person JOIN Group_Performance_Role
        ON Group_Person.group_id = Group_Performance_Role.group_id
    WHERE performance_id = 27

    UNION

    SELECT person_id
    FROM Person_Performance_MultiRole
    WHERE performance_id = 27

    UNION

    SELECT person_id
    FROM Person_Performance_SingleRole
    WHERE performance_id = 27

)

Note hat this lists people at most once, even when they are involved with the performance in multiple roles (e.g. a same person can be a "Conductor" and a member of a group that has a role on the same performance).

To also get their role names, you could:

SELECT Person.*, group_role_name
FROM Person
    JOIN Group_Person
        ON Person.person_id = Group_Person.person_id
    JOIN Group_Performance_Role
        ON Group_Person.group_id = Group_Performance_Role.group_id
WHERE performance_id = 27

UNION ALL

SELECT Person.*, person_multirole_name
FROM Person
    JOIN Person_Performance_MultiRole
        ON Person.person_id = Person_Performance_MultiRole.person_id
WHERE performance_id = 27

UNION ALL

SELECT Person.*, person_singlerole_name
FROM Person
    JOIN Person_Performance_SingleRole
        ON Person.person_id = Person_Performance_SingleRole.person_id
WHERE performance_id = 27

As you can see, we keep making the model more and more precise, but also more and more complex. And we haven't even gone into songs and albums, and evolving group members (etc...) yet. I guess the onus is on you to decide where is the right balance between "precision" and simplicity.

Community
  • 1
  • 1
Branko Dimitrijevic
  • 50,809
  • 10
  • 93
  • 167
  • You are correct - I do not want "groups in groups"... however this model is a little too complex for what I'm building. Thankfully, the majority of the data I'm working with already exists - everything from the 1930s to very recently. I'm a second-year BIT student and I've only done 1 "databases" paper. I didn't know you could have inheritance or abstraction when defining database tables - it's not like I'm ever going to be instantiating them, right? Or am I misunderstanding? – Alex McMillan Sep 20 '12 at 10:18
  • @AlexMcMillan Conceptually, a table can be viewed as a "class" and a row in that table as an "object" or "instance" of that class. So inheritance between tables makes perfect sense. Unfortunately, relational DBMSes don't support inheritance directly - you'd have to _emulate_ it (as explained in my link). OTOH, ER notation does recognize inheritance. – Branko Dimitrijevic Sep 20 '12 at 10:23
  • First, I appreciate all the work you've just done to describe this - thank you :) Second, can you give me an example of the SQL that would be required to get all people who performed any role in performance 27, along with the role they performed? – Alex McMillan Sep 20 '12 at 10:43
  • @AlexMcMillan In which model? – Branko Dimitrijevic Sep 20 '12 at 11:00
  • An Entity maps nicely to a Class. It will help you if they are complimentary. – Jodrell Sep 20 '12 at 11:58
2

Your ultimate goal is to store a database of performances right?

So a performance is performed by some catergory of performer, arranged by some catergory of composer and produced by some catergory of producer etc. I think you need an abstract entity to represent all these posibilities. The best noun I can summon right now is a Credit, since you would "extend the credits for your name." (Morisette 1995)

So, the way I imagine it, you would have several categories of Credit, at the first level I imagine these to be Person, Group which is a set of Person s and Organisation which would somthing like "Parlephone" or "Island Records" etc.

There may be sub categories of these Credit categories, depending on the attibutes you wish to store. However, I imagine each Performance would have a number of PerformanceCredit relationships and each PerformanceCredit relationship would have a foriegn key to PerformanceCreditType.


All this ignores any relationship with Song which I think is logically seperate from Performance, Song would have its own SongCredit relationships, the SongCreditType "Writer" being the obvious one that comes to mind. Each Song being related to a number of Performance s

This all extends nicely out to Recording (DVD, 78, LP, MP3, etc.) which would be a collection of Performance es but can and do have independent Credit s of thier own.


I think this makes sense because I assume you'll be getting this information from the credits.

I think you'd need this level of flexibility. Consider if I wanted to report on everything to do with "Paul McCartney", his direct credits, both solo and in groups, as a writer, composer, musician and producer are vast. Then consider performances of songs he has written and composed by other musiacians etc.

Jodrell
  • 34,946
  • 5
  • 87
  • 124
  • I like this answer, but I'm not sure I follow it properly :) Essentially you're saying to replace the "role" table with a "PerformanceCreditType" table and add some kind of "credits" table in place of the "group_performance_role" table? – Alex McMillan Sep 20 '12 at 09:49
  • essentially yes, so the credits table would hold the PK for credit and any attributes shared by all credits (I can't think of one instantly.) – Jodrell Sep 20 '12 at 09:52
  • Say Paul McCartney is represented with a group.group_id of 42. I can easily get everything he was involved in by `select * from group_performance_role where group_id = 42`. From those results, I can find all performances where he played a certain role, or all roles that he has performed... etc – Alex McMillan Sep 20 '12 at 09:58
  • Well, Credit would have an optional one to one with Group, Person or Organisation. – Jodrell Sep 20 '12 at 09:58
  • @Alex I was approaching the problem with a clean slate, not really referring to your proposed solution. If they look similar I guess that is a good thing. – Jodrell Sep 20 '12 at 10:03
1

I think the way you have it probably makes sense. I assume that you are modeling both Groups and Group Members/People separately because there are different operations/actions that you want to perform against groups, and group members (if not why bother modeling group members at all).

If that's the case, then I assume in the case of John Lennon you want to be able to perform both the Person operations and Group operations against him, so having him show up twice in the DB, as a Group and a Group Member makes sense, since the two entities represent different roles that John Lennon plays in your domain.

Dylan Smith
  • 22,069
  • 2
  • 47
  • 62
0
  • A Record has many Songs.
  • Each Song has a single Artist - which has a name.
  • An Artist has one or more versions
  • An ArtistVersion has one or more Members who are Performers

eg

Records : 
   1 Give Peace a Chance
   2 Penny Lane

Artists
   3 The Beatles
   4 Plastic Ono Band

Songs 
   5 4 Give Peace a Chance
   6 3 Penny Lane
   7 3 Strawberry Fields Forever

RecordSongs
   1 - 5
   2 - 6
   2 - 7

ArtistVersions
   8 - The Beatles v1 
   9 - Plastic Ono Band v1

Performers
   10 - Ringo Starr
   11 - John Lennon
   12 - Yoko Ono

ArtistVersionMembers
   8 - 10 
   8 - 11
   9 - 11
   9 - 12
podiluska
  • 50,950
  • 7
  • 98
  • 104
  • I'm sorry I don't understand - how are there different "versions" of a performer? Was there a "Beatles 2.0" ?? – Alex McMillan Sep 20 '12 at 09:51
  • Not in the beatles, no, but what about an artist where the lineup changes, eg: Sugababes, Genesis, etc. – podiluska Sep 20 '12 at 09:53
  • Oh - all "variances" are considered to always be group members. So if, for example, Ringo Starr left the Beatles and was replaced by Joe Smith, my spec requires that all 5 names appear as group members. – Alex McMillan Sep 20 '12 at 10:03
  • Ok. So get rid of versions and link Artists directly to members then. – podiluska Sep 20 '12 at 10:04