Data Normalization

G

Guest

I'm trying to think through the best way to normalize this data. It will be
my first database. I'm working with Access 2003. I want to create a database
with data entry of my piano music. I have lots of piano books and those books
have many of the same songs but just different arrangements. I want to be
able to type in a song title and get a report of whether I have piano music
for that title and if so, what music books to look in and on what page. At
some point, I may expand the database to include the arranger's name. I
started to approach this by creating a Song table with the Primary key being
incremental numbering of each song but after entering over 600 song titles
and retyping the song book where the song is located up to 50 or 100 times, I
thought there must be a more efficient way to do this. So then I thought I
might should approach this by having a Song Book table. There would be less
data entry if I could enter the name of the song book once, then when
entering the songs that are in that book, I could just pick that book title
from a drop-down menu. This is my first attempt at putting together a simple
database. I've had only one chapter in one class dedicated to the basics of
Access.
 
G

Guest

"retyping the song book where the song is located up to 50 or 100 times"

LoL,

this a case for a many-to-many relationship

Each song book contains many songs
Each song can be in many books

tble_songbook
SongbookID (PK)

tble_Details
SongbookID (FK)
TitleID (FK)

tble_SongTitle
TitleID (PK)

The ID fields should be long integer number types.

In the relationship view (Tools) show the three tables. Drag the
"SongbookID" from the "songbook" table to the "details" table. Do the same
with "TitleID". Ensure referential integrity with each.

Add all other required fields to the "songbook" and "Songtitle" tables.

When you come to design the form use the wizard. Put the "Songbook" into the
main form and "Songtitle" into the subform.

Then for each songbook you can list all the titles. You will need a combo
box to select from the "Songtitles" table to insert into the subform.

That is basically it (for now that is...!)
 
G

Guest

All of this has been so helpful and I've gotten further along in the process.
However, in thinking about designing the form and thinking about the song
titles being a drop-down menu, that menu could become extremely long. Am I
understanding this correctly? When thinking about song titles being chosen
from a drop-down menu, that menu could be hundreds or thousands of
possibilities. I'm sure I'm missing something here.
 
G

Guest

You are correct.

Since one person can write many songs you can include an extra table:

tble_songbook
SongbookID (PK)

tble_Details
SongbookID (FK)
TitleID (FK)

tble_SongTitle
TitleID (PK)
CompID (FK)

tble_Composer
CompID (PK)


Something else you can add is a combo with the first three letters of a
song. For this, build a query so that you get a list of all your song titles
and then insert an expression that will grab the first three letters and make
them distinct values.

So you can then choose all songs with the same first three letters (or four
letters).
 
G

Guest

Okay. I'm thinking about this in real-life terms. Let's start with me
purchasing a new piano book. I need to enter the book title and all its songs
into my database via a data entry form. The songbook title will be unique but
the songs can have duplicates from other books. For example, the song Amazing
Grace may have many instances. When I'm entering the song title, "Amazing
Grace" in the database, are you saying I could type the first 3 or 4 letters
to pull up a list of songs already entered into the database that begin with
those letters and then choose that song title? And, what if I'm entering a
song title that has never been entered into the database before? I really
want to simplify the data entry side of this database. I'm about to decide I
just need to go take another class in Access. Thanks for your help.
 
G

Guest

It could be worth going on another course but there is nothing better than
learning Access by trial and error.

If you create a main form and subform using these two tables:

tble_Composer
CompID (PK)
Comp_Name

tble_SongTitle
TitleID (PK)
CompID (FK)
Song_Title


Each composer's name occurs once and then you can list all the songs for
that composer in the subform. You can then use this information in the
"tble_details" junction subform.

The other thing I would add is that you base the form and subform on a query
rather than the tables themselves. Every time you add a new composer they can
be sorted in alphabetical order when you re-open the form.

If you give me your personal email address, would it be easier if I send it
to you or are you ok so far?

But write it so that it isn't easily recognisable to spamming software like

joe (dot) smith (at) h o t m a i l (dot) com
 
A

Amy Blankenship

scubadiver said:
It could be worth going on another course but there is nothing better than
learning Access by trial and error.

If you create a main form and subform using these two tables:

tble_Composer
CompID (PK)
Comp_Name

tble_SongTitle
TitleID (PK)
CompID (FK)
Song_Title


Each composer's name occurs once and then you can list all the songs for
that composer in the subform. You can then use this information in the
"tble_details" junction subform.

The other thing I would add is that you base the form and subform on a
query
rather than the tables themselves. Every time you add a new composer they
can
be sorted in alphabetical order when you re-open the form.

If you give me your personal email address, would it be easier if I send
it
to you or are you ok so far?

But write it so that it isn't easily recognisable to spamming software
like


It seems to me that she's not interested in the actual composer, but the
arranger. The song/arranger combination will be associated, but not
necessarily unique to, a particular book. So, it seems to me that for the
data design that all she has to do is add an Arranger table and an
ArrangerID field to the Details table you described earlier. If I were
designing the forms for her, I'd create a Books form that contained a
drop-down for Song and Arranger, using a Not in List event to pop up a Song
Entry and Arranger Entry form. Keep in mind that while you may indeed have
hundreds or thousands of songs, you can set up your combobox so that it
starts trying to "guess" what song you are entering as you type. So, if you
are entering "Moonlight Sonata", you may only have to type "Mo" before it
selects the right song.

HTH;

Amy
 
G

Guest

Any, you are definitely addressing some of the issues I'm grapling with. I
want to keep the data entry side of this application as simple as possible
and your solution sounds good. However, I'm realizing that you're both making
references to things that weren't covered in my one chapter of Intro to
Access. I was naive to think I could build this database after my one chapter
of exposure to Access. Part of my struggle is that I don't learn on my own
very well. I need the structure of a class with teacher and book. Perhaps
this is partly because I'm probably extremely ADD (Attention Deficit
Disorder). I'm not sure of the quickest way to get to where it is I need to
be in order to build this database.
 
G

Guest

Perhaps I might make a few points supplementary to those already made her.

1. You are not limited to one method of data entry. You can for instance
have a Songbooks form with a Songs subform, i.e. the songbook is entered in
the parent form and the songs entered in the subform by selecting from a
combo box. The combo box's list should be multi-columned so you can
distinguish between different songs with same title, e.g. La Mer ( I know the
Debussy piece is really a tone poem not a song, but I'd guess there must be
piano transcriptions of it). A new song can be entered via the combo box
with some code in its NotInList event procedure (I've included an example
below. You can also have a Songs form with a Songbooks subform, i.e. you
enter a song and select which songbooks contain the song in the subform. At
any time you can chose which method to use depending on the circumstances.
One you've entered data via one form the other will reflect the new data of
course, so if you've entered a songbook and then selected the songs it
contains, if you then go to one of those songs in the Songs form its
Songbooks subform will include the songbook you entered.

2. Don't use distinct tables for composers and arrangers. As a composer
might also be an arranger there is the risk of inconsistencies arising if the
same person's details are recorded in two tables ( I once came across a
database in which there were three different versions of my name as the
author of technical papers!). There are two ways you could approach this.

One would be to regard whether a person is a composer or arranger as an
attribute of the relationship type between songs and people, i.e. to have a
columns SongID, PersonID and something like Role in the table which models
this relationship type.

The other approach, is to see Composers and Arrangers as subtypes (aka
sub-classes) of type People. Types and subtypes are modelled in a relational
database by having one table for the (super)type and one for each subtype,
the latter being related one-to-one to the (super)type. The primary key of
each subtype table is therefore also a foreign key referencing the primary
key of its (super)type. In your case you'd have a table People and tables
Composers and Arrangers.

Which of these approaches is most appropriate depends on whether there are
attributes of composers which are not shared by arrangers. Attributes like
FirstName, LastName etc are obviously shared so would go in the People table.
Whether there are any non-shared attributes which would go in either of the
other two tables I'll leave you to decide. From a layman's point of view it
seems unlikely to me that there are and the first approach is probably the
most appropriate. With this a song in a songbook would be modelled by two
rows in the table if it had a composer and an arranger, i.e. having the same
SongID and SongbookID but different Role values, Composer in one row and
Arranger in the other. It would have the same PersonID value if the composer
and arranger are one and the same person, different ones if they are not.

Its worth noting here that SongID, PersonID and Role are in fact a composite
foreign key in this table as they will reference a further table in which the
composition or arrangement of a song by a particular person is recorded.
That table itself models a relationship between Songs and People, each of
which would be modelled by a table. You'll see that the model is becoming a
little more extended now; I'd advise that you spend some time drawing it out
diagrammatically on paper before creating the tables. That way you can
mentally test it and make any necessary amendments before getting in too deep.

3. Generating a report on the basis of a song title will be quite a simple
task, simply requiring you to join the necessary tables in a query for use as
the report's RecordSource and creating a dialog form in which you can select
the song title and open the report filtered to that song. You could use a
combo box to select the song, or if you wanted something more flexible you
could use a multi-select list box to select one or more songs simultaneously.
Whichever you use there are pretty standard routines for this.

Finally here's the sample code for a combo box's NotInList event procedure
which I mentioned above. This is for adding a new city, and opens a form in
which other data about the new city is added, but the code in your case would
be very similar:

Private Sub cboCities_NotInList(NewData As String, Response As Integer)

Dim ctrl As Control
Dim strMessage As String

Set ctrl = Me.ActiveControl
strMessage = "Add " & NewData & " to list?"

If MsgBox(strMessage, vbYesNo + vbQuestion) = vbYes Then
DoCmd.OpenForm "frmCities", _
DataMode:=acFormAdd, _
WindowMode:=acDialog, _
OpenArgs:=NewData
' ensure frmCities closed
DoCmd.Close acForm, "frmCities"
' ensure city has been added
If Not IsNull(DLookup("CityID", "Cities", "City = """ & _
NewData & """")) Then
Response = acDataErrAdded
Else
strMessage = NewData & " was not added to Cities table."
MsgBox strMessage, vbInformation, "Warning"
Response = acDataErrContinue
ctrl.Undo
End If
Else
Response = acDataErrContinue
ctrl.Undo
End If

End Sub

Along with the above code the following goes in the frmCities form's Open
event procedure to set the default value of the city control in the form to
the value which was entered in the combo box on the first form:

Private Sub Form_Open(Cancel As Integer)

If Not IsNull(Me.OpenArgs) Then
Me.City.DefaultValue = """" & Me.OpenArgs & """"
End If

End Sub


Ken Sheridan
Stafford, England
 
G

Guest

Thank you guys so much! I think I've really got to get a book and do some
reading so I can benefit from all your help.

Sylvia
 
J

Jamie Collins

there is nothing better than
learning Access by trial and error.

I wonder if your clients or their end users (airline passengers?
patients? etc) would agree?

Jamie.

--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top