views:

247

answers:

6

A dairy farmer, who is also a part-time cartoonist, has several herds of cows. He has assigned each cow to a particular herd. In each herd, the farmer has one cow that is his favorite - often that cow is featured in a cartoon. A few malcontents in each herd, mainly those who feel they should have appeared in the cartoon, disagree with the farmer's choice of a favorite cow, whom they disparagingly refer to as the sacred cow. As a result, each herd now has elected a herd leader.

This is what I think the tables should look like can you let me know if it can be done better? So far I'm doing a many to many using the favorite table as the intermediate is this the best possible solution also no SQL statements are needed this is just for design purposes.

Thank you in advance

Table Herd           Table Favorite               Table Cartoon   Table Cow
PK herdID          Intermediate Table             PK cartoonID     PK cowID
   herdname                                          cartoonTitle     cowName
   herdleader                                        cartoonType
                                                     cartoonDate

edited image @ 3:01pmEST is this correct?

cowErd

added new image @ 8:57am 7/20/2010 can some one critique this ERD please Erd2

added new image @ 12:47pm 7/20/2010 unless there's any objections this is the final draft per Mark's explanation mark ERD

+1  A: 

I like that you've actually tried to do this on your own. In fact you are nearly there, so you haven't done a bad job at all.

Let's look at this from an Object / Entity perspective.

The entities include the following:

  • Cows
  • Herds
  • CowHerds (you have to associate a cow to a heard)
  • CowCartoon (one of the cows is a favorite, you can always reference this cow's heard by going up the chain using the cowid)

Cows

  • CowID (Primary Key)
  • CowName (varchar, this could potentially be the key but cow's may have the same name right?)

Herds

  • HerdID (Primary Key)
  • HerdName (This could also be the primary key, ultimately this is your decision)
  • CowID (Foreign Key, remember each herd has a cow leader, you can even separate this in another table, but it really is not worth it)

CowHerds

  • CowID (fK to cows)
  • HerdID (fk to heards)

The combination of the above field serves as a primary key

CowCartoon

  • CartoonID (primary key of a cartoon)
  • CowID (the 'favorite' cow, references which cow the farmer is going to write a cartoon about)
  • Published Date (date published)
  • Title ....

As mentioned in the comments, you can also get rid of the CowHerds table and reference the HerdID directly in the Cows table.

JonH
CowHerds table is, in my opinion, in correct -- a Cow can belong to one and only one herd, so the Cow table should have a HerdID column that is a foreign key back to Herd. The propsed design permits each cow to be a member of each herd. Further, the Herd table needs two references back to the Cow table - the sacred cow and the herd leader, which may or may not be the same cow.
Adam Musch
when you say references do you mean a recursive relationship?
Michael Quiles
When I say reference, I mean foreign key constraint.
Adam Musch
@Adam: While I agree that the CowHerds table is unnecessary, I would suggest that only the leader cow belongs in the herd table. While it's not explicitly stated, it seems that there is one sacred cow per cartoon, not per herd. Different cartoons could have different sacred cows, which could both belong to the same herd.
Allan
@Allan: I disagree with your interpretation of the requirements, as the requirements do explicity state "In **each herd**, the farmer **has one cow** that is his favorite - often that cow is featured in a cartoon." Similarly, "**each herd** now **has** elected **a herd leader**." As such, SacredCowID and LeaderCowID belong in the Herd table as foreign key columns back to Cow. Heck, I don't see any requirement to track which cow appears in which cartoon at all, but that I suspect is much more open to debate.
Adam Musch
Edited for emphasis on quotes.
Adam Musch
@Adam Musch - You could do it that way, and I agree with you however it was not originally mentioned when the OP first asked. But yes you could include the HerdID right directly in the Cows table. It really can work either way. Of course without the cow heard table it is much simpler solution.
JonH
OK now I'm confused, which would be the simplest way of implementing this I will upload my diagram in a second so that you guys can tell me what I did wrong and why. thanks for your help guys really appreciate it.
Michael Quiles
@Michael Quiles - If one cow can only belong to one herd, then you do not need the CowHerds table. Simply have a herds table with a herdID. And in your cows table add a HerdID field to the cow table. That way a cow only belongs to one herd and you can define it when you first create the cow.
JonH
#High on a hill lived a lonely CowHerd...# -- makes me wonder how a farmer differentiates their herds in reality. I suspect it is by some physical attribute (by breed, by the field the cow currently occupies, etc) rather than by assigning a `HerdID` identifier. I have almost zero domain knowledge here but I find `CowHerds` to be jarring. What about `HerdManagement`?
onedaywhen
@onedaywhen - It's just terminology. Whatever is easier for you. Again you may not need that table you could reference a HerdID within the cow's table.
JonH
@JonH: "It's just terminology" -- I disagree: it's actually metadata. "CowHerd" makes me think of "Goatherd" which is a person who herds goats, so straight off I've got the wrong idea. I find it interesting that the lack of a familiar 'real world' term for the allocation of cows to herds makes me think this is a contrived concept and rather it would be determined by attributes e.g. current physical location, breed, owner, etc.
onedaywhen
@onedaywhen - i disagree with you, as it is really up to the op to give the relationship name, it really isn't that big of a deal.
JonH
A: 

That answer seems good to me.

Richard Housham
@Richard Housham - This is a comment not an answer. Make sure if you have a comment you add it to the original OP question using Add Comment. Otherwise people will downvote this as it is not an answer to the question.
JonH
@JonH: people tend to leave comments as answers if their rep isn't enough (50). I do agree, the ensuing downvotes on answers only serve to drag them further away from the 50-rep requirement for commenting though.
BoltClock
@BoltClock - As you notice though it generally goes in the opposite direction :-).
JonH
@JonH: yeah, unfortunately :/
BoltClock
+5  A: 

Michael:

What are the nouns in the problem statement, and how many of them are there?

Farmer  - There is one farmer
Cow     - There are many cows
Herd    - There are many herds
Cartoon - There are many cartoons

As there is only one farmer, leave him out of future discussions. These are your base entities.

What attributes does each entity have?

Cow     - each cow has a name
        - each cow is a member of a herd
Herd    - each herd has a name
        - each herd has a cow that is the sacred cow
        - each herd has a cow that is the herd leader
Cartoon - each cartoon has a name
        - each cartoon may have a cow that appears in it 
             (not specified definitively)

So some of these attributes reference other entites, and some do not. The attributes that do not reference other base entities are simple. The other ones require more consideration.

Can a cow be a member of more than one herd?
Must a cow be a member of a herd?
Can a herd have more than one cow that is the sacred cow?
Must each herd have a cow that is the sacred cow?
Can a herd have more than one cow that is the herd leader?
Must each herd have a cow that is the herd leader?

These questions help outline whether or not the relationships between the entities are mandatory or optional, and whether the relationships are one-to-many or many-to-many.

Adam Musch
+4  A: 

A discussion item, so I've made it a Community Wiki.

One thing that the relational model doesn't do well is enforcing that the SacredCow and HerdLeader held at the Herd level actually point to Cows that are members of that Herd.

Say your Herds are Star and Cross. The details for the 'Star' Herd may give Rigel as the SacredCow and Castor as the HerdLeader, but the 'Cow' table may show Castor as a member of the 'Cross' Herd. In practice, when creating a new Herd, you face a chicken and the egg scenario when you either have a Herd with no Cows (and hence no HerdLeader/SacredCow) or a Cow without a Herd.

An alternative model would have the 'Cow' table indicating whether a particular Cow is the HerdLeader and/or SacredCow for their herd. [In a physical implementation, it would be possible for a unique constraint to enforce that every Herd only had one cow that was a SacredCow and one cow that was a HerdLeader.] .The "Herd" table wouldn't have the SacredCow or HerdLeader. This model would fail to enforce that every herd had a HerdLeader and a SacredCow.

Both are models. Both have flaws. At the logical level, I'd probably go with the former as it is more Normalised. At the physical, I'd be be considering which inconsistency would be more troublesome and more likely to occur, and I'd be picking the model that best prevented it.

Gary
@Gary, the relational model, if implemented fully, can enforce these constraints easily. Unfortunately, the RM isn't fully implemented in most RDBMS's out there :(
Jeffrey Kemp
@Jeffrey: Example?
Chris Kaminski
@Chris Kaminski: for example, a TRDBMS could feature database constraints (for which the overall database must satisfy some specific condition, where the condition in question can refer multiple tables) and multiple assignment (data may be updated in many tables and be considered an atomic action for the purposes of constraint checking) e.g. a D language as specified in The Herd Manifesto... sorry, I mean, The Third Manifesto (http://en.wikipedia.org/wiki/The_Third_Manifesto).
onedaywhen
+1 for the Herd Manifesto!
Mark Bannister
thanks onedaywhen, you said it :)
Jeffrey Kemp
+1  A: 

Part 1.

If the following are true:

each Cow must be in exactly one Herd
a Herd must have a sacredCow and a herdLeader
a sacredCow for a Herd must be a Cow in that Herd
a herdLeader for a Herd must be a different Cow in that Herd

Then you could implement these rules with this partial model:

Cow (cowID, herdID) (all mandatory columns)
- primary key (cowID)
- unique (herdID, cowID)
- foreign key (herdID) references Herd (herdID)

Herd (herdID, sacredCow, herdLeader) (all mandatory columns)
- primary key (herdID)
- foreign key (herdID, sacredCow) references Cow (herdID, cowID)
- foreign key (herdID, herdLeader) references Cow (herdID, cowID)
- constraint (sacredCow != herdLeader)

Notice how the FK relationships include the herdID, not just the cowID. This ensures that only those Cows in a Herd may be made the sacredCow or herdLeader for that Herd.

This design makes things a little tricky to implement but not impossible. The foreign keys on Herd would have to be made deferrable in a database like Oracle, since we need to be able to insert the rows for a Herd before we can insert the rows for the Cows, and a Herd requires at least two Cows (the sacredCow and the herdLeader).

Part 2.

The next challenge is to implement the following constraint:

only a Sacred Cow may be featured in a Cartoon

One way to do this may be to split Cows into two separate relations: SacredCows and NonSacredCows.

SacredCow (sacredCowID, herdID) (all mandatory columns)
- primary key (sacredCowID)
- unique (herdID, sacredCowID)
- foreign key (herdID) references Herd (herdID)

NonSacredCow (nonSacredCowID, herdID) (all mandatory columns)
- primary key (nonSacredCowID)
- unique (herdID, nonSacredCowID)
- foreign key (herdID) references Herd (herdID)

Herd (herdID, sacredCow, herdLeader)
- primary key (herdID)
- foreign key (herdID, sacredCow) references SacredCow (herdID, sacredCowID)
- foreign key (herdID, herdLeader) references NonSacredCow (herdID, nonSacredCowID)

Cartoon (cartoonID, featuredCow) (all mandatory columns)
- primary key (cartoonID)
- forign key (featuredID) references SacredCow (sacredCowID)

(In this design, the constraint (sacredCow != herdLeader) is no longer required because they are now different cows by definition.)

Jeffrey Kemp
Sacred cows and non-sacred cows are both cows - ie. they share the same attributes and the same key, so they should be the same entity / table.
Mark Bannister
@Mark, that is not enough. It is perfectly acceptable to have same set of attributes in two entities if the propositions/semantics applied to entities differ.
Unreason
@Unreason, you can in SQL, but not in a properly normalised schema.
Mark Bannister
@Mark Bannister, in this design SacredCow and NonSacredCow *do* have different attributes and different keys (they just happen to have the same names, which may be confusing but is not disallowed).
Jeffrey Kemp
I'll edit it to be more clear.
Jeffrey Kemp
To make it even more explicit: what I'm saying in this model is that, regardless of whether a farmer might say that there is no difference between a SacredCow and a NonSacredCow, in the *context of this model*, the cartoonist (and the cows themselves!) do consider them to be fundamentally different.
Jeffrey Kemp
@Mark Bannister: you are incorrect in saying that a properly normalized database cannot have two tables with the same attributes and keys. I think you meant to say that it violates the principle of orthogonal design.
onedaywhen
@onedaywhen: nope - "the key, the whole key and nothing but the key".
Mark Bannister
@Mark Bannister: simple example: `Employees` table with `emp_ID` key plus a bunch of attributes, an `Unsalaried` table with just the `emp_ID` key and nothing but the `emp_ID` key, and a further table `SalariesUnknown` table again with with just the `emp_ID` key and nothing but the `emp_ID key`. Both `Unsalaried` and `SalariesUnknown` are in 5NF yet they share the same keys (`emp_ID`) and attributes (none).
onedaywhen
+1  A: 

Assuming a Cow can only belong to one herd at a time and assuming that more than one cow (from different herds, obviously) can appear in the same cartoon, my suggestion:

Table Herd

Herd ID (PK)
Herd Name

Table Cow

Cow ID (PK)
Herd ID (FK)
Cow Name
Is Leader (Boolean)
Is Sacred (Boolean)

Table Cartoon

Cartoon ID (PK)
Cartoon Title
Cartoon Type
Cartoon Date

Table Appearance

Cow ID (PK)
Cartoon ID (PK)
Mark Bannister