|
Your teacher is right, 3NF would be the minimum requirement before I'd call it a well-designed database. You are right too; in the real world, databases are created when needed, and grow over time - not all of them are designed upfront.
Whenever I can, I try and normalize. Your example would make it very hard to get the complete address-details of the customer, since you'd be seeing a similar construction with ZipCodes and streets.
Digital Thunder wrote: would you leave the three different telephone attributes in the customer table and invite null entries?
You don't want to do this;
SELECT ([phone1], [phone2], [phone3]) from ..
Before you know it, customers will want to add extra information, like a short description (e.g. "this number only between 1 and 5 am") or a bool column to flag disconnected lines.
That would lead to a
SELECT ([phone1], [phone1desc], [phone2], [phone2desc], [phone3] ..
Might not sound very useful in this particular example, but I'm sure that most of us had to update a similar database at least once in their career. Imagine you have a table that all of a sudden would receive four or five more attributes
I are Troll
|
|
|
|
|
Eddy Vluggen wrote: You don't want to do this;
SELECT ([phone1], [phone2], [phone3]) from ..
Before you know it, customers will want to add extra information, like a short description (e.g. "this number only between 1 and 5 am") or a bool column to flag disconnected lines.
That would lead to a
SELECT ([phone1], [phone1desc], [phone2], [phone2desc], [phone3] ..
Hmmm, I see what your saying. So, I suppose the answer to my original question is "it depends" judging by the range of replies that the question solicited. It depends on what the database is actually designed to achieve in the first place and what are the consequences moving from a theoretically correct design to a design that has compromises which fly in the face of conventional theory.
My thanks go out to all of you that took the trouble to reply to the original question.
There is only one satisfying way to boot a computer.
|
|
|
|
|
Digital Thunder wrote: s moving from a theoretically correct design to a design that has compromises
Stick to the theoretically correct design, and make sure that you can explain why you denormalized that particular table.
Your teach has prolly given some good arguments why you should apply at least 3NF. A good reason for denormalization would be partitioning - if the table were too large, and you'd like to divide it over two databases.
IRL you'll find lots of denormalized databases, simply because there's lots of people creating databases who never heard of Codd, or decided to take a shortcut.
I are Troll
|
|
|
|
|
Eddy Vluggen wrote: Your teach has prolly given some good arguments why you should apply at least 3NF.
He certainly did. Basically, we were told, without normalising to 3NF we wouldn't be able to get the database to do what we want it to do and that it would be rather error prone and that if we wanted to make any money out of database design then we had better normalise to 3NF otherwise we would be penniless! The latter is a very convincing argument.
There is only one satisfying way to boot a computer.
|
|
|
|
|
I have learned through experience to do what your instructor describes -- things will become more complex over time. Do it correctly now.
"It's better to have it and not need it than to need it and not have it."
"A stitch in time saves nine."
At one place I worked, we needed to hold a credit card number for each account (actually, account-holders also had the option not to provide one) -- great, it (and its type; Master Card, Visa, etc.) was in the Account table. Then we had a customer who wanted to store two credit card numbers (so there would be a backup in case the other was declined ) -- OK, the DBAs added it to the Account table with another field to indicate which one had been charged most recently. Then we had another customer who also wanted us to support ACH transactions against bank accounts -- oh, crap -- the DBAs added yet more fields to the Account table. I left the company after writing a document explaining that I thought that all that data should be moved to a separate table before things got completely out of hand.
I suspect that in your case you want to generalize it to some sort of "contact method" table which includes telephone numbers, email addresses, icy cucumbers, etc.
|
|
|
|
|
I inherited a table with over 250 columns. Many no longer used, several should have been in their own table.
But the table grew just like yours (need this one thing, well now I need this one other thing).
Building normalized to start is the best path.
|
|
|
|
|
PIEBALDconsult wrote: I suspect that in your case you want to generalize it to some sort of "contact method" table which includes telephone numbers, email addresses, icy cucumbers, etc.
Not quite sure about the icy cucumbers but yes, you've hit the nail on the head, that's exactly what it's for. I actually finished college 5 years ago, and this is the first occasion that has presented itself to put into practice what I actually learned, so I'm a bit rusty at the minute and having to rely on lecture notes, assignments and Database Systems (2nd Ed.) by Begg and Connolly, which is heavy going at times to say the least.
There is only one satisfying way to boot a computer.
|
|
|
|
|
Digital Thunder wrote: heavy going at times
Yeah, the other week I again looked up (Wikipedia and others) third-normal-form and again couldn't make sense of the discussion. I absolutely know how to use third-normal-form, but the terms that are used to describe it are non-sensical (unless there is someone there actually telling you and applying it to some data).
It's kind of like being able to read, write, and speak a language fluently but not understanding linguistics. Really, only cunning linguists need to know what the term "pluperfect" means or even that it exists. And all those hours spent diagramming sentences didn't help us speak betterishly.
|
|
|
|
|
PIEBALDconsult wrote: unless there is someone there actually telling you and applying it to some data
I know EXACTLY what you mean. When the lecturer is explaining examples to drive home a point, it's quite obvious what he is actually getting at. However, I to have looked at a few examples on the web and some of them have only served to confuse me even more than I was! I did however, find a very good article that condensed a lot of detail into relatively few pages and the examples given really did a good job in explaining the detail.
There is only one satisfying way to boot a computer.
|
|
|
|
|
Digital Thunder wrote: confuse me even more
Exactly.
Digital Thunder wrote: a very good article
Got a link?
|
|
|
|
|
|
Query for Getting Max number.
For Example: I have Department and Employee
For DeptId 1: Emp No 12,16,19
and For 2: 18,21,17
For 3: 27,28,16
I have to get Max(EmpNo) For department. If I want to get Max(EmpNo) for Dept(1,2)
output will be 19,21.
How can I get this using sqlserver2005
|
|
|
|
|
using row_number and partition
SELECT DeptId ,EmpNo
FROM (SELECT
*,
ROW_NUMBER() OVER(PARTITION BY DeptId ORDER BY EmpNo DESC)HighID FROM tableName) X
WHERE X.HighID = 1
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Thank you so much. Its working fine ...
|
|
|
|
|
See the replies from Luc and Goutam, my answer is NOT the simplest way.
Comes from applying the wrong tool for the job.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Why not in this simple way
SELECT DEPTID, MAX(EMPNO) FROM TABLENAME GROUP BY DEPTID
|
|
|
|
|
that looks overly complex. wouldn't the following work (I think it does in MySQL):
SELECT DeptId,Max(EmpNo) 'maxEmpNo' FROM table1 GROUP BY DeptId ORDER BY DeptId
|
|
|
|
|
Hi. I am creating a form that will show results of a query in a "Datasheet View" - multiple records on one form with a header at the top of each column of data.
I want to know which event can i use to react to a new record being "loaded"?
My desire is to display a different label (text control) only when a field's value (date) changes by record. If I have several records, i want a visual indicator showing change in dates (one label for all Day-1's data, then only one (new) label for all Day-2's data, then only one (new) label for all Day-3's data, ....)
Thanks.
Johnny J
|
|
|
|
|
From my understanding of Access, you can't have multiple header while displaying data in "Datasheet View", there is only one set of headings at the top of the grid.
You can change the background color of cells to give the effect of a "green bar" report making the Day 1 data stand out from the Day 2 data. I believe you want to play around with the Events "Before Render", Before Layout, etc.
I've never done it with a datasheet view, but I have created Reports where I would BOLD dates of tasks that were late. The event in the report I believe are "On Print".
Good luck.
|
|
|
|
|
Thanks for the advice.
I added a text control, separate from the record "set" to which the rest of the form is related. I just shoved the other controls to the right so that I can squeeze my text control to look like it occupies it's own column.
My idea was to have my new text control filled with the date, for that group of records with the same date. Only showing that date once.
I have my own function that identifies the date for each record and could do something like MyTextCtrl.value = strDateLabel (when I figure out how to react to the right Event.)
Thanks again, i will give your ideas a try.
JJM
|
|
|
|
|
Ah ha. I think I see what you are doing.
How about this ...
When you are building your dataset with a query, add a column where you can calculate a value you want displayed.
For example:
SELECT Payroll.WKNum, IIf([wkNum] Mod 2=0,"Even","Odd") AS OddEven
FROM Payroll;
This query displays the Payroll Week Number and a Text value of "Even or Odd"
This would free the DataSheet View from having to do any logic processing on the dataset, it would just display it.
If you need more complex logic, maybe you could extend this by manipulate a temporary table, then display that contents.
Give it a shot.
|
|
|
|
|
I am trying to pack four address lines, to leave no blank between the lines and no null values.
The code below is so horrid, it could qualify quite well to the coding horror forum.
This is also a question so I post it here.
The question is :
- How would you write this more elegantly ?
It would be fun to compare various other ways, I will perhaps post some
DECLARE @line1 AS VARCHAR(255)
DECLARE @line2 AS VARCHAR(255)
DECLARE @line3 AS VARCHAR(255)
DECLARE @line4 AS VARCHAR(255)
SET @line1 = '12 orchard st '
SET @line2 = NULL
SET @line3 = ' '
SET @line4 = 'BATH'
SET @line1 = RTRIM(LTRIM(COALESCE(@line1,'')))
SET @line2 = RTRIM(LTRIM(COALESCE(@line2,'')))
SET @line3 = RTRIM(LTRIM(COALESCE(@line3,'')))
SET @line4 = RTRIM(LTRIM(COALESCE(@line4,'')))
DECLARE @cpt INTEGER
WHILE @line1 = '' AND @cpt<3
BEGIN
SET @line1 = @line2
SET @line2 = @line3
SET @line3 = @line4
SET @line4 = ''
SET @cpt = @cpt + 1
END
SET @cpt = 0
WHILE @line2 = '' AND @cpt<2
BEGIN
SET @line2 = @line3
SET @line3 = @line4
SET @line4 = ''
SET @cpt = @cpt + 1
END
IF @line3 = ''
BEGIN
SET @line3 = @line4
SET @line4 = ''
END
PRINT 'Line 1:' + @line1
PRINT 'Line 2:' + @line2
PRINT 'Line 3:' + @line3
PRINT 'Line 4:' + @line4
|
|
|
|
|
If you want to just make a single string then there is a solution
DECLARE @line1 AS VARCHAR(255)
DECLARE @line2 AS VARCHAR(255)
DECLARE @line3 AS VARCHAR(255)
DECLARE @line4 AS VARCHAR(255)
DECLARE @line5 AS VARCHAR(2000)
SET @line1 = '12 orchard st '
SET @line2 = NULL
SET @line3 = ' '
SET @line4 = 'BATH'
SET @line5 = (SELECT RTRIM(LTRIM(COALESCE(@line1,''))) +
CASE WHEN LEN(RTRIM(LTRIM(COALESCE(@line2,'')))) > 0 THEN CHAR(13) ELSE '' END + RTRIM(LTRIM(COALESCE(@line2,''))) +
CASE WHEN LEN(RTRIM(LTRIM(COALESCE(@line3,'')))) > 0 THEN CHAR(13) ELSE '' END + RTRIM(LTRIM(COALESCE(@line3,''))) +
CASE WHEN LEN(RTRIM(LTRIM(COALESCE(@line4,'')))) > 0 THEN CHAR(13) ELSE '' END + RTRIM(LTRIM(COALESCE(@line4,''))))
PRINT @line5
|
|
|
|
|
Then you would need
SET @line1 = SUBSTRING(line5, [something here], [something here])
SET @line2 = SUBSTRING(line5, [something here], [something here])
SET @line3 = SUBSTRING(line5, [something here], [something here])
SET @line4 = SUBSTRING(line5, [something here], [something here])
Wouldn't you?
|
|
|
|
|
Well, thats why i said in my post If you want it in a single string.
and then this will not solve your purpose
|
|
|
|
|