views:

467

answers:

5

I need to store several date values in a database field. These values will be tied to a "User" such that each user will have their own unique set of these several date values.

I could use a one-to-many relationship here but each user will have exactly 4 date values tied to them so I feel that a one-to-many table would be overkill (in many ways e.g. speed) but if I needed to query against them I would need those 4 values to be in different fields e.g. MyDate1 MyDate2 ... etc. but then the SQL command to fetch it out would have to check for 4 values each time.

So the one-to-many relationship would probably be the best solution, but is there a better/cleaner/faster/whatever another way around? Am I designing it correctly?

The platform is MS SQL 2005 but solution on any platform will do, I'm mostly looking for proper db designing techniques.

EDIT: The 4 fields represent 4 instances of the same thing.

A: 

How about having 4 fields alongwith User ID (if you are sure, it wont exceed that)?

shahkalpesh
+2  A: 

If you do it as four separate fields, then you don't have to join. To Save the query syntax from being too horrible, you could write:

SELECT * FROM MyTable WHERE 'DateLiteral' IN (MyDate1, MyDate2, MyDate3, MyDate4);

As mentioned in comments, the IN operator is pretty specific when it comes to date fields (down to the last (milli)second). You can always use date time functions on the subquery, but BETWEEN is unusable:

SELECT * FROM MyTable WHERE date_trunc('hour', 'DateLiteral') 
IN (date_trunc('hour', MyDate1), date_trunc('hour', MyDate2), date_trunc('hour', MyDate3), date_trunc('hour', MyDate4));
Douglas Mayle
haha that's cool... I havn't thought of that.. stupid me.
chakrit
Date comparisons are usually tricker than that as datetime fields store the time down to (at least) the second. If you're storing the dates as strings, this wouldn't apply.
tvanfosson
Ah... indeed but actually the precision of values wouldn't be a problem in my case but a BETWEEN query would still require typing the 4 fields explicitly?
chakrit
A: 

Create four date fields and store the dates in the fields. The date fields might be part of your user table, or they might be in some other table joined to the user table in a one-to-one relationship. It's your call.

twblamer
+1  A: 

For what it's worth, the normalized design would be to store the dates as rows in a dependent table.

Storing multiple values in a single column is not a normalized design; normalization explicitly means each column has exactly one value.

You can make sure no more than four rows are inserted into the dependent table this way:

 CREATE TABLE ThisManyDates (n INT PRIMARY KEY);
 INSERT INTO ThisManyDates VALUES (1), (2), (3), (4);

 CREATE TABLE UserDates (
   User_ID INT REFERENCES Users,
   n INT REFERENCES ThisManyDates,
   Date_Value DATE NOT NULL,
   PRIMARY KEY (User_ID, n)
 );

However, this design doesn't allow you make the date values mandatory.

Bill Karwin
Ah that n INT REFERENCES is new to me. Is it supported on other platforms as well?... and please consider that normalization has its cost in terms of speed and complexity as well.
chakrit
REFERENCES is a part of standard SQL, and should be supported by every database that supports foreign keys.
Bill Karwin
Normalization does come with some costs, but are they more or less costly than the gymnastics required by a denormalized design? Your original problem is a case in point. It's best to start with a normalized design, and denormalize sparingly.
Bill Karwin
The gymnastics balance you mention isn't very obvious in my case. It's kind of a one-off application. It's a form-filling application that would only last 1 month and I only had 2 weeks development time. I'm curious as to what tips/techniques are available if I could go with denormalized design.
chakrit
+2  A: 

Some databases like Firebird have array datatype, which does exactly what you described. It is declared something like this:

alter table t1 add MyDate[4] date;
Milan Babuškov
Last time I heard about Firebird was some years ago.. haha.. gotta look at it now.
chakrit
Firebird comes from InterBase, which has had an array data type for at least 15 years.
Bill Karwin