Normalized or not is not a disease (at least, as I see it) and not an
absolute matter, but more about the way to arrange the data in the table so
that the tool at hand (the database engine) will simplify OUR job. Having
fields like Reason1, Reason2, Reason3 is generally a bad idea because:
- if you need Reason4, you need to add the field, to the table, AND to
change the FORMS using that table, so they now display that new control too,
AND probably the SQL statements implying that table (Maintenance problems)
- nothing really forbid someone, half asleep, to mistakingly repeat
Reason1 in Reason7 field (user input error detections)
- deleting Reason2 could be easily done, by putting a 0 in it, but
then, when a new reason is to be added, you have the extra work to look at
the first 'reason' available (spotting data)
- space is used to accomodate the maximum number of reasons, even if
most records may have only one reason!
So, instead of:
ClientID PartNumber Jan Feb Mar Apr
1010 1011 1 0 0 5
1010 1034 0 0 0 2
An alternative design can be:
ClientID PartNumber MonthName Amount
1010 1011 Jan 1
1010 1011 Apr 5
1010 1034 Apr 2
Sure, sure, sure, it is harder to read, for a HUMAN person, but much better
for the database tool (and anyhow, you can switch it back in an easier
reading presentation with a Crosstab query, if required)
As example,you can define an index made of the three first fields, not
allowing duplication, and then, no one would be able to enter TWO records
for the same client, same PartNumber, same MonthName. It is easy to add a
new amount for a new MonthName, given a client and a part number: append a
record. It is easy to delete an amount for a month, given a client and a
part number: you delete the record. Search of the maximum amount per
client is easy: GROUP on client and MAX(amount)... the first design would
oblige us to scan all the month fields, horizontally... but SQL does not
work horizontally, without supplying ALL the involved fields.
Note that in your case, if "Reason1" is just a place holder, ie, not like a
month name, not and indication that it is more important than "Reason2", the
alternate design can be simply:
ClientID PartNumber Amount
1010 1011 1
1010 1011 5
1010 1034 2
Anyhow, the alternate design will be easier to answer to the question: what
is the TOTAL amount, per client, per part|Number:
SELECT clientID, partNumber, SUM(amont) As totalAmount
FROM alternateDesign
GROUP BY clientID, partNumber
while, with the initial design, it would have been:
SELECT clientID, partNumber, Reason1+Reason2+Reason3+ ... + Reason32
FROM firstDesign
and YOU will have to modify that query if ever a Reason33 field is added to
the table!
If you want to find the maximum amount, per client, per part number:
SELECT clientID, partNumber, MAX(amount)
FROM alternateDesign
GROUP BY clientID, partNumber
while, with the first design... well, I don't want to type iif until
tomorrow morning...
Sure, to get the TOP 3, alternate design:
SELECT TOP 3 clientID, partNumber, SUM(amont) As totalAmount
FROM alternateDesign
GROUP BY clientID, partNumber
ORDER BY SUM(amount) DESC
compared with the first design:
SELECT TOP 3 clientID, partNumber, Reason1+Reason2+Reason3+ ... + Reason32
FROM firstDesign
ORDER BY Reason1+Reason2+Reason3+ ... + Reason32 DESC
the immediate advantage (typing) is not evident, but still, maintenance
problem (adding Reason33) are possible. The alternate (normalized) design
can add as many reasons as you have space, since you add RECORDS, not
FIELDS. (Well, we are limited to a total of 2Gig, but that is a very large
limit, usually)
So, again, normalization is not much an absolute. As example: would we
use:
ClientID FirstName MiddleName LastName
1010 Joe W Blow
or
ClientID NamePosition Name
1010 1 Joe
1010 2 W
1010 3 Blow
or
ClientID ClientName
1010 Jow W Blow
Well, that depends! Generally the third design will be use, even if it less
normalized than the first, which is itself less normalized than the second
design. To the question: up to were we normalize? my answer is: up to what
you really need. If you never need to decompose the ClientName, clearly, the
third design is the way to go, here.
So, I don't really know why used "Reason1" , "Reason2" , and so on, but
such progression, xxx1, xxx2, xxx3, ... , on the fields names is OFTEN a
poor design, for a database.
Vanderghast, Access MVP