[comp.databases] Time related records

srini@ultra.com (S. Srinivasan) (06/28/90)

In <1082@kirk.nmg.bu.oz> cameron@kirk.nmg.bu.oz (Cameron Stevenson) writes:

>We are holding information within a table for a key register. Some of
>the columns are the key number, the person the key is issued to, and
>the issue date. Now supposing that person leaves, the key is handed in
>and issued to a new person. Now the information within the table is
>altered to reflect that change, but the problem... how can I store
>the fact that at some stage person A was issued with that key.

Assumption:	

RELATION Key_Register (	Key#, Person, Issue_Date, Return_Date,
			<other attributes>
		      );


Your hesitation to increase your data storage space by copying tuples
containing Returned_Key information into another historical table,
leads me to believe that your <other_attributes> are significantly
large.  

Why don't you split your relation into:

---------------------------------------------------------------
1. RELATION Key_Issues ( Key#, Person#, Issue_Date, Return_Date);

	INDEX on (Key#);
	INDEX on (Person#);
	UNIQUE INDEX on (Key#, Return_Date);
/* A <NULL> value for Return_Date in the tuple
   which represents a key which has been issued.
   A non-<NULL> value in which the key has been
   returned.  A key which has not been issued out
   to anyone should be present with the Person#
   being the ADMIN.  The UNIQUE index will force you to 
   update the returned-key typle because for a key,
   only one record can be <NULL>
 */

2. RELATION Key_Register ( Key#, <other_attributes> );
	UNIQUE INDEX on (Key#);

3. RELATION Person_Names (Person#, <person_info>);
	UNIQUE INDEX on (Person #);

I suspect this is not normalized enough, because you
could delete all information about Keys from the 
Key_Register table, and leave tuples in Key_Issues
"dangling".  Likewise for Persons.  But your 4GL
should be able to enforce that.
---------------------------------------------------------------

As for your request to store temporal information in general,
doesn't Oracle provide a DATE type of attribute?
If it is internally stored as a 32-bit integer, then
temporal precedence should be simple to establish.

* The Key to the Issue is to have only Date at a Time,
  otherwise you would be in a Unique position indeed!

:-) S. Srinivasan
[Ultra Network Technologies, San Jose, CA]
"The fastest computer networks in the world"
*

carl@eleazar.dartmouth.edu (Carl Pedersen) (06/29/90)

My attempt to mail this bounced, so here is my reply to Cameron
Stevenson.

If you have a unique id for the key and for each person, and the
time the key was given to the person, then these three items
together comprise a unique key for the table.

Why not just leave the old records there?

The person who has the key now is the one who took it out most
recently.

   select who from t where key_id = 12345 and checked_out =
     (select max(checked_out) from t where key_id = 12345);

You may want to keep track of the times when the key is not
checked out to anyone.  In that case, if storage isn't a big
issue, you could just have a special "person" who would "hold"
all keys that are not checked out.

reg@unify.uucp (Russell Grau) (06/29/90)

In article <1082@kirk.nmg.bu.oz> cameron@kirk.nmg.bu.oz (Cameron Stevenson) writes:
>This may seem a trivial question for some, but here goes...
>
No question is trivial if you don't know the answer...

>I'm trying to find an elegant way to store time related records with
>our database (ORACLE). By this I don't mean, time in the sense of the
>time lapsed eg. how many minutes, seconds, etc., but in relation to 
>changes in information in columns over time. 
>
>Perhaps an example will explain the problem better...
>We are holding information within a table for a key register. Some of
>the columns are the key number, the person the key is issued to, and
>the issue date. Now supposing that person leaves, the key is handed in
>and issued to a new person. Now the information within the table is
>altered to reflect that change, but the problem... how can I store
>the fact that at some stage person A was issued with that key.
>
>I'm sure there are plenty of ways of doing this, but most that I can
>think of involve copying the relevant rows from the 'current' table
>to an 'historical' table, with subsequent increase in the amount of
>data being stored, and fairly strict control on that copy/modify process
>through the application front-end.
>
>So, back to the original question, the answer to which may be staring me
>in the face...
>
>Is there an elegant way to store this time related information? Are there
>any good textual references somebody could point me towards? Any help
>would be appreciated.
>
>Cameron Stephenson                         Telephone  +61 75 951220
>Bond University
>Gold Coast    Australia


Cameron -

I would recommend that you create a "person" table if you do not already 
have one.  This person table would include the name, department, etc., 
etc. that you need for this person.  It would also include as a foreign
key the primary key for your "key register" table, the date that the key
was issued and the date that the key was turned into HQ.

This is the classic one to many relationship with the one being the "key
register" and the many being the "person".

Should be fun....
-- 
/*****************************************************************************/
/*   Russell Grau            (916) 920-9092                 reg@unify.UUCP   */
/* Disclaimer - "I speak for myself, not my company"                         */
/* {{ucdavis,csun,lll-crg}!csusac,pyramid,sequent}!unify!reg                 */

cameron@kirk.nmg.bu.oz (Cameron Stevenson) (06/29/90)

This may seem a trivial question for some, but here goes...

I'm trying to find an elegant way to store time related records with
our database (ORACLE). By this I don't mean, time in the sense of the
time lapsed eg. how many minutes, seconds, etc., but in relation to 
changes in information in columns over time. 

Perhaps an example will explain the problem better...
We are holding information within a table for a key register. Some of
the columns are the key number, the person the key is issued to, and
the issue date. Now supposing that person leaves, the key is handed in
and issued to a new person. Now the information within the table is
altered to reflect that change, but the problem... how can I store
the fact that at some stage person A was issued with that key.

I'm sure there are plenty of ways of doing this, but most that I can
think of involve copying the relevant rows from the 'current' table
to an 'historical' table, with subsequent increase in the amount of
data being stored, and fairly strict control on that copy/modify process
through the application front-end.

So, back to the original question, the answer to which may be staring me
in the face...

Is there an elegant way to store this time related information? Are there
any good textual references somebody could point me towards? Any help
would be appreciated.

Cameron Stephenson                         Telephone  +61 75 951220
Bond University
Gold Coast    Australia

rbw00@uts.amdahl.com (Richard Wilmot) (06/29/90)

cameron@kirk.nmg.bu.oz (Cameron Stevenson) writes:

> This may seem a trivial question for some, but here goes...

> I'm trying to find an elegant way to store time related records with
> our database (ORACLE). By this I don't mean, time in the sense of the
> time lapsed eg. how many minutes, seconds, etc., but in relation to
> changes in information in columns over time.

> Perhaps an example will explain the problem better...
> We are holding information within a table for a key register. Some of
> the columns are the key number, the person the key is issued to, and
> the issue date. Now supposing that person leaves, the key is handed in
> and issued to a new person. Now the information within the table is
> altered to reflect that change, but the problem... how can I store
> the fact that at some stage person A was issued with that key.

> I'm sure there are plenty of ways of doing this, but most that I can
> think of involve copying the relevant rows from the 'current' table
> to an 'historical' table, with subsequent increase in the amount of
> data being stored, and fairly strict control on that copy/modify process
> through the application front-end.

> So, back to the original question, the answer to which may be staring me
> in the face...

> Is there an elegant way to store this time related information? Are there
> any good textual references somebody could point me towards? Any help
> would be appreciated.

I think you should try some entity-relationship analysis. Offhand, it
appears that you are trying to store data that pertains to 2 entities
(keys and persons) and 1 relationship: issued_to.

The following design might work as a first cut:

PERSON_TBL (person_ID, name, phone, etc)
            ---------                      person_ID is unique identifier
KEY_TBL (key#, key_opens)
         ----                              key# is unique identifier
                                           assuming a key only opens 1 thing.
                                           Else need a relationship which
                                           may be easier to add now.

ISSUED_TO (key#, person_ID, issue_date, issue_time, return_date, return_time)
           ----  ---------  ----------  ----------
                                           key#, person_ID, issue_date,
                                           and issue_time taken together
                                           are unique identifiers in the
                                           issued_to relationship table.

Now you can have keys that have never been issued (no issued_to rows), keys
which have been returned and not reissued (every issue data and time has
a nonnull return date and time). You don't need a special history table.
I believe that when history and present states are seen as just another
(time) dimension then it is much more natural and far easier to write query
programs which need to use both current and historical information.

This approach will store some identifier data seemingly redundantly
in the ISSUED_TO relationship table but only for those objects which
have (or have had) multiple relationships. All others will only be ssored
once. If you try to compress the issued_to relationship information into
one of the other entity's tables you will very likely end up with update
anomalies: e.g. can't have a person without a key or a key which hasn't
been issued.

For more on these and related problems see:
 "Foreign Keys Decrease Adaptability of Database Designs"
  Wilmot, R. B., _CACM_, Dec. 1984

Hope this helps.
-- 
 Dick Wilmot  (408) 746-6108   | I declaim these as my own ramblings.

ghm@ccadfa.adfa.oz.au (Geoff Miller) (06/29/90)

In <1082@kirk.nmg.bu.oz> cameron@kirk.nmg.bu.oz (Cameron Stevenson) writes:

>We are holding information within a table for a key register. Some of
>the columns are the key number, the person the key is issued to, and
>the issue date. Now supposing that person leaves, the key is handed in
>and issued to a new person. Now the information within the table is
>altered to reflect that change, but the problem... how can I store
>the fact that at some stage person A was issued with that key.

We had a similar problem with a File Registry System, where we need to
identify the current location of a file *quickly* but also record the
movement history.  We store the location as a multivalued field, and
at every movement insert the new location as the first multivalue.  An
associated MV field record the date of the movement, so we can if necessary
strip off movements preceding a given date.  

Of course, we are working with a Pick-like system (Prime "Information")
which makes this kind of thing very easy....

Geoff Miller
ghm@cc.adfa.oz.au

rbw00@uts.amdahl.com (Richard Wilmot) (06/29/90)

In Message-ID: <7vi4uht@unify.uucp> reg@unify.uucp (Russell Grau)
replies to Cameron Stephenson's request for assistance with a history
keeping application with a design suggestion:

> Cameron -

> I would recommend that you create a "person" table if you do not already
> have one.  This person table would include the name, department, etc.,
> etc. that you need for this person.  It would also include as a foreign
> key the primary key for your "key register" table, the date that the key
> was issued and the date that the key was turned into HQ.

> This is the classic one to many relationship with the one being the "key
> register" and the many being the "person".

> Should be fun....

But if the person table includes as a foreign key the primary key (e.g. key#)
of the key_register table then a person can only have one key at a time.
There are two entity types here: people and keys. There is also a relationship
between some of the entity occurrences: issued_to. Another problem is that
if I delete a person record (row) then I will have lost some of the history
regarding the key that person last possessed. Additionally a person's key
possession history cannot be tracked. We could not answer whether John Doe
ever had access to a particular if he had been issued a new one so that
his key history were overlayed with new key issue information. In short
this appears to be a many-to-many relationship: each person can have
multiple keys and over time each key may have been issued to multiple
people. Many-to-many relationships require relationship tables to store
the information about the relationships. In general, choosing to model
a relationship as one-to-many is risky compared with electing many-to-many
if application/business needs might at some point require it to become
many-to-many because application logic assuming the former is hard to
change whereas applications developed for the many-to-many case easily
handle the one-to-many case.

Storing information about the people to key relationships in a saparate
relationship table will remove the above update anomalies and tracking
limitations. It will then be necessary, of course, to have an integrity
constraint to disallow removal of an object which is still involved in
a relationship or to cascade such a delete (e.g. maybe we don't care which
keys a terminating employee had). Doesn't Oracle support integrity constraints?
-- 
 Dick Wilmot  (408) 746-6108   | I declaim these as my own ramblings.

cameron@kirk.nmg.bu.oz (Cameron Stevenson) (07/04/90)

From article <0ejm02D3b48801@amdahl.uts.amdahl.com>, by rbw00@uts.amdahl.com (Richard Wilmot):
 < reply deleted >

 Thanks very much Richard. The key register is indeed a many-many
 relationship, and if I read your message correctly you suggested I set up
 the tables as follows:
 1. a person table, with each row representing one person
 2. a key table, with each row representing one key
 3. a person-key relationship table, with each row representing a relationship
 between a person and a key - ie. a row for when a person is issued with a key.

 Sounds fine, and the logic even seems to work - ie. if a person is deleted
 from the person table (they leave) their entries in the person-key table
 can be retained for future reference. Let's complicate the issue (believe
 me, not unnecessarily)...

 What is really needed from the application are answers to the following
 questions:
 1. Who has/has had access to this room?
 2. Which room/rooms can this person get access to?

 Now we introduce a second set of many-many relationships, as one key can
 access many rooms, and one room could be accessed by many keys. Does this
 affect the overall model design, or do I just create a key-room relationship
 table? The query which traces a person through to the room should be
 interesting... (perhaps a view would be the way to go?)

 Just as a final thought to confuse it further... there are always multiple
 copies of the same key. This means the key number is not a unique instance.

 Once again, thanks very much to all who replied. 

 Cameron Stephenson                           Telephone +61 75 951220
 Bond University
 Gold Coast    Australia