views:

66

answers:

3

Hi all.

I have a coding problem where I have to store a 'note' and the dates the note applies to. Think of:

Note 1 Hi, today Mr Client rang arranging these appointments. 30/8/2009, 31/8/2009, 5/9/2009

Note 2 Business as usual. 30/8/2009

Note 3 Restaurant is shut. 6/9/2009

I need to store the following data in a database, while maintaining indexes for efficient retrieval, that is, my client application will need to pick a date, and retrieve all the notes related to that date, exclusively or partially.

I've discussed with a few colleagues and friends, and have come down to this design. Please note I want to be able to store all the information in one table, or more if the design is elegant.

> Date Bitmap | Month | Year | Note
> 101..         9       2009   Blah Blah     // applies to 1st and 3rd
> 0001...       10      2009   Blah2         // applies to the 4th
> 100           9       2009   Blah23

When the user selects from a multi date picker the following date: 1st of September He will get Blah Blah and Blah23. A single date time object will repeat the note, or force the creation of another table with a foreign key.

In the sense that I could store in the first column what days of the month the note applies to. In a bitmap, things could be super-efficient. Any other ways (linked tables with Note-ID, or a table with all the days with IDs) have all resulted in ugly duplication of either the note field, or repeated dates. I also don't want to think about having a Text field with sets of dates with separators, and ugly code that will parse it upon search.

I have the luxury of time on this project as you can tell.

But how can the client application RETRIEVE say, all the notes for a given set of dates? Is there any bit operations in MSSQL? So I can retrieve all the rows, with say, a '1' in the 5th and 7th bit in that binary field?

I can't use BETWEEN as I might have sporadic dates that are not in a range or anything or the sort. Think of having a datatype where it could represent any number from 1 to 31. That's how I thought of a bitmap.

Let me also say that we could add an extra text field in which the real dates (in real text) will be populated by a routine. But for the rest, this application will be the main interface and rarely users will have to look at the ugly table.

Am I over-engineering, or can you help me?

Thanks for all your replies.

Leo

+2  A: 

Yes, you are over-engineering.

Simply create a single datetime column, and index it. If you want to split up a datetime, use the built in functions like datepart().

"How can the client application RETRIEVE say, all the notes for a given set of dates?"

By executing a query with a WHERE clause BETWEEN the start and end dates.

Declare the 'Note' field as varchar(n) [n up to 8000 approx.). It only uses the space taken up by the note not the maximum defined size.

Mitch Wheat
I understand, I also considered the fact that the note system is going to get really big, with sometimes notes applying to over 60 days. What you saying is have 60 records with the same 255-byte note.
lb
@Leo, no you won't want to repeat the same note for each date. You will have another table that stores a datetime stamp along with a foreign key to the note table. That way you can find all dates that relate to a note, and all notes that relate to a date. There will be an entry this table for each note for each date.
Chris Porter
Will a date time stamp be able to specify a multiple set of dates, say 4th, 6th .. etc. (not a range)My sincere apologies for being so critical.
lb
@Leo: A DateTime column only stores **one** Date/Time value per row. See my comment about using effective/expiry datetime columns to manage notes covering more than one date.
OMG Ponies
+1  A: 

If the application will need to pick a date, and retrieve all the notes related to that date (exclusively or partially), then you need to store the date using the DateTime datatype.

If the business note for a note is such that it can span days, your NOTES table needs EFFECTIVE_DATE and EXPIRY_DATE DateTime columns. The dates could be the same day, or a couple apart.

If you want the note text/body to apply to periodic days (IE Jan 1st, 13th, 21st), then you'd need two tables: NOTES, and NOTE_ACTIVITY. NOTE_ACTIVITY would contain the note_id, along with effective and expiry dates. I just don't see how you could support sporadic dates associated to a single body of text any other way in a database.

OMG Ponies
I basically need some notes saying "In June blah blah." that note will apply to each day of June. If in the client application they do a look up for the 4th of June, that note will come up, as well as another note that applies to say, the 4th and 6th, or another one for the 4th only.
lb
Rexem, my apologies for being over critical. I understand that your method will work in case of a range? What about a date here and there?Thanks - I'm probably causing anger, but this has caused me many headaches because I'm too overcritical too!
lb
+1  A: 

I would personally split this to two tables

NOTE
int Id
varchar NoteText

NOTEACTIVITY
int Id
DateTime ActivityDate
int NoteId

This keeps your queries simple and allows for plenty of flexibility in the future. It will mean that if a note applies to three dates you have one entry in the Note table, and three entries in the NoteActivity table. In some ways you would be likely to run into this issue with your existing design. If a client wanted a note to apply to the first of every month you would be duplicating the row (including note) 12 times?

Alternatively, if you've already decided that your note bitmap idea is the correct way, then consider storing the day numbers instead of a bitmap, so you could store '[1][5][30]'. This may make your queries easier to run, by searching for rows that contain '[5]' in that column for example

PaulG