473,748 Members | 2,308 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Finding the natural key

Whenever I want help on a query, I get told my design is wrong, So this
time I'm posting a message during the design phase: How am I going to
perfectly design the following?

We want to be able to track time for users for multiple modules, for
now a Schedule module and a Punchlist module. These modules already
exist and there are dozens of other modules which we will add to the
list as well, two or three at a time - so it should be possibly to add
to the list of related modules fairly easily.

In my mind the natural key is the UserOrContactId (an id for a
particular person), the date the time is for and ReferenceId to the
module it is in, either PunchlistItemId or ScheduleTaskId. I haven't
done the foreign keys yet and will do that once the table design is
settled. The MinutesSpent is going to be the minutes the person spent
doing a particular schedule task or punchlist item, which will be
converted from hours and minutes to just minutes for the database with
a constraint for total miuntes per day not being more than 24 hours.
Create and Update User/Time is a standard thing we put on all our
tables for auditing purposes. The ForDate will be the date the hours
happen so if the natural key is done right that will take care of
checking that two entries aren't made on the same day, i.e. the total
horus should just be updated if an entry exists.

The problem is that I can't make the natural key a primary key because
you can't have nulls in the primary key, i.e. it will be either a
PunchlistItem OR a Schedule Task, but not both for a particular record.
In the past I have done something like RefType = 'Schedule', RefId =
ScheduleTaskId, but then foreign keys can't be applied.

So what's the perfect solution so that I won't get heckled for design
when I ask a query question about it in a few months? Celko, get it all
out of your system - I don't understand database design, blah, blah,
blah, but show me the perfect solution.

CREATE TABLE [dbo].[TimeSpent](
[UserOrContactId] [int] NOT NULL,
[ForDate] [smalldatetime] NOT NULL,
[PunchlistItemId] [int] NULL,
[ScheduleTaskId] [int] NULL,
[MinutesSpent] [int] NOT NULL,
[Description] [varchar](100) COLLATE SQL_Latin1_Gene ral_CP1_CI_AS NOT
NULL,
[Notes] [text] COLLATE SQL_Latin1_Gene ral_CP1_CI_AS NOT NULL,
[CreateUser] [int] NOT NULL,
[CreateTime] [smalldatetime] NOT NULL,
[UpdateUser] [int] NOT NULL,
[UpdateTime] [smalldatetime] NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO
ALTER TABLE [dbo].[TimeSpent] WITH CHECK ADD CONSTRAINT [CK_RefIds]
CHECK (([PunchlistItemId] IS NOT NULL OR [ScheduleTaskId] IS NOT
NULL))
GO

Mar 15 '06 #1
13 3212
>> Whenever I want help on a query, I get told my design is wrong, So this
time I'm posting a message during the design phase: How am I going to
perfectly design the following?
First of all asking questions regarding a specific database design on a
public newsgroup is inherently a bad idea. Logical database design following
business/conceptual model and as such nobody in this newsgroup is familiar
with your business model other than you. Your problem may well be related to
the rest of the design and may affect other relevant subsystems/ modules/
infrastructure etc. And the advice which you receive here may be based on
what others perceive as the problem and may not be the actual design
problem, not to mention the chances of misunderstandin g and
misinterpretati on are very high.
We want to be able to track time for users for multiple modules, for now
a Schedule module and a Punchlist module. These modules already exist and
there are dozens of other modules which we will add to the list as well,
two or three at a time - so it should be possibly to add to the list of
related modules fairly easily.
Based on this narrative, one could conclude that a module is a well defined
entity and could come up with a table like:

CREATE TABLE Modules (
Module_id INT NOT NULL PRIMARY KEY,
Module_name VARCHAR(15) NOT NULL ) ;

INSERT Modules SELECT 1, 'Schedule' ;
INSERT Modules SELECT 1, 'Punchlist' ;
....
In my mind the natural key is the UserOrContactId (an id for a particular
person), the date the time is for and ReferenceId to the module it is in,
either PunchlistItemId or ScheduleTaskId. I haven't done the foreign keys
yet and will do that once the table design is settled. The MinutesSpent
is going to be the minutes the person spent doing a particular schedule
task or punchlist item, which will be converted from hours and minutes to
just minutes for the database with a constraint for total miuntes per day
not being more than 24 hours.


This does not make full sense, unless you can explain precisely each aspect
of the system within the limits of a newsgroup post.

Based on the narrative, if a person works in a module at a given time, you
can represent those facts in tables like:

CREATE TABLE Persons (
Person_id INT NOT NULL PRIMARY KEY,
Name VARCHAR(40) NOT NULL,
... );

INSERT Persons SELECT 1, 'Joe' ;
INSERT Persons SELECT 2, 'Kim' ;
....

CREATE TABLE Activities (
Person_id NOT NULL
REFERENCES Persons ( Person_id )
ON UPDATE CASCADE
ON DELETE CASCADE,
Module_id NOT NULL
REFERENCES Modules ( Module_id )
ON UPDATE CASCADE
ON DELETE CASCADE,
Begin_date INT NOT NULL DEFAULT CURRENT TIMESTAMP,
End_date INT NOT NULL DEFAULT ('9999-12-31'),
...
PRIMARY KEY (Person_id, Module_id ) );

INSERT Activities SELECT 1, 1, '2006-01-01', '2006-01-03', ... ;
INSERT Activities SELECT 1, 2, '2006-02-01', '2006-02-15', ... ;
INSERT Activities SELECT 2, 1, '2006-01-02', '2006-01-14', ... ;
INSERT Activities SELECT 2, 2, '2006-01-28', '2006-02-20', ... ;

Having distinct temporal attributes for each module, allows you to infer the
time spent on each module by a person. If multiple people can work on the
same module, consider adding the Begin_Date column to the key. In that case,
if this table is being referenced by many other tables, it might be a good
idea to consider a surrogate.

Like I said, unless a thorough analysis of the business model is done, most
of the effort will be wasted over nonsensical arguments over silly issues
like what is "natural" and what is not. If you find this time critical and
the task is overwhelming, perhaps considering a professional hire might
help.

--
Anith
Mar 15 '06 #2
What Anith said. Have a modules table. Much happier in the long run.
Aniht has a typo in the insert statement - they can't both have the
same id. I'm sure it is a typo.

Also,why description AND notes? Is description from a pick list? if
so, have a descriptions table.

Anohter module could be "Vacation", and pretty soon you have a standard
time tracking system.

Mar 15 '06 #3
A user is going to do some work on a particular day and then they are
going to record the fact that they spent 30 minutes, 2 hours or
whatever on a *particular schedule task* and want to report on it
later. Are you saying I should turn the 30 minutes into a date range?
The user won't specify that information - they will just know that on
Tuesday they spent an hour working on schedule task 1 on Monday and two
hours working on schedule task 2 on Tuesday.

I do like the Modules table idea, I am going to play with the table
design a bit and see how that works - Thanks. But I need to use some
combination of the Module and the line item in the module as part of
the key to uniqueness.

Mar 15 '06 #4
Oh yeah.. And why are your dates created as integers?

I'll probably take out the description column, but sometimes people
want a short description of something but they also want to type a
novel to describe it.. Having one short and one long text fields lets
them do that.

Mar 15 '06 #5
I played with adding a Module table but then I lose ref integrity when
the module line items are deleted. So I would need to add a
ModuleLineItem table as well (??) and then I have ref integrity
problems with the other tables linking to it...

P.S. Identity columns are awesome.

Mar 15 '06 #6
pb648174 (go****@webpaul .net) writes:
A user is going to do some work on a particular day and then they are
going to record the fact that they spent 30 minutes, 2 hours or
whatever on a *particular schedule task* and want to report on it
later. Are you saying I should turn the 30 minutes into a date range?
The user won't specify that information - they will just know that on
Tuesday they spent an hour working on schedule task 1 on Monday and two
hours working on schedule task 2 on Tuesday.
Given that information, it seems reasonable to just have a counter,
suggestively in minutes. (Disclaimer: I did not read your original post
very closely.)

....however, it reminds me of our old time-reporting system we had my
office for several years, a hack developed by a colleague over a
Christmas holiday. Here you could enter start and stop for activities.
You didn't have to, and the only thing that mattered was was the hours
worked. But it was very user-friendly, since I didn't have to count
hours in my head, I could just write down how my day had been, easily
rearranging some hours if I wanted to save some typing.
Oh yeah.. And why are your dates created as integers?


I suspect that was a type of Anith. Maybe he had hours or minutes
originally and then changed his mind.

In any case, there is a flaw with his date formats, remove the hyphens:
99991231 etc, to make sure that the dates are always interpreted the
same.
--
Erland Sommarskog, SQL Server MVP, es****@sommarsk og.se

Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/pro...ads/books.mspx
Books Online for SQL Server 2000 at
http://www.microsoft.com/sql/prodinf...ons/books.mspx
Mar 15 '06 #7
That is a good idea, I think I might include that feature, but also
allow minutes/hours to be entered. In that case, should I have just a
start and end date and just make one up if they enter minutes, or just
have the minutes as null if they start/stop and vice versa? I think I
lean towards the second option so later I'll be able to tell if they
did start/stop or manually entered their time.

Mar 16 '06 #8
Ok, so here is the final solution as I have it now, sans the start/stop
stuff and references to other tables:

CREATE TABLE [dbo].[TimeSpentItem](
[Id] [int] IDENTITY(1,1) NOT NULL,
[PunchlistItemId] [int] NULL,
[ScheduleTaskId] [int] NULL,
CONSTRAINT [PK_TimeSpentIte m] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

GO
ALTER TABLE [dbo].[TimeSpentItem] WITH CHECK ADD CONSTRAINT
[CK_TimeSpentIte m_ValidReferenc e] CHECK (([PunchlistItemId] IS NOT
NULL OR [ScheduleTaskId] IS NOT NULL))
GO

CREATE TABLE [dbo].[TimeSpentActual](
[UserOrContactId] [int] NOT NULL,
[ForDate] [smalldatetime] NOT NULL,
[TimeSpentItemId] [int] NOT NULL,
[Minutes] [int] NOT NULL,
[Notes] [text] COLLATE SQL_Latin1_Gene ral_CP1_CI_AS NOT NULL,
[CreateUser] [int] NOT NULL,
[CreateTime] [smalldatetime] NOT NULL,
[UpdateUser] [int] NOT NULL,
[UpdateTime] [smalldatetime] NOT NULL,
CONSTRAINT [PK_TimeSpentAct ual_1] PRIMARY KEY CLUSTERED
(
[UserOrContactId] ASC,
[ForDate] ASC,
[TimeSpentItemId] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO
ALTER TABLE [dbo].[TimeSpentActual] WITH CHECK ADD CONSTRAINT
[FK_TimeSpentAct ual_TimeSpentIt emId] FOREIGN KEY([TimeSpentItemId])
REFERENCES [dbo].[TimeSpentItem] ([Id])
GO
ALTER TABLE [dbo].[TimeSpentActual] WITH CHECK ADD CONSTRAINT
[CK_TimeSpentAct ual_ValidForDat e] CHECK ((datepart(hour ,[ForDate])=(0)
AND datepart(minute ,[ForDate])=(0) AND datepart(second ,[ForDate])=(0)))
GO
ALTER TABLE [dbo].[TimeSpentActual] WITH CHECK ADD CONSTRAINT
[CK_TimeSpentAct ual_ValidTime] CHECK ((isnull([Minutes],(0))<(1439)))

Mar 16 '06 #9
>played with adding a Module table but then I lose ref integrity when
the module line items are deleted. So I would need to add a

so, don't let them be deleted. Trust me on this one, you REALLY want to
have a modules table.

Mar 16 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

17
23172
by: Sean Ross | last post by:
Hi. Recently I made a small script to do some file transferring (among other things). I wanted to monitor the progress of the file transfer, so I needed to know the size of the files I was transferring. Finding out how to get this information took some time (reading the manuals - googling did not prove worthwhile). Anyway, I did eventually figure out how to do it (there are a few ways, including os.path.getsize(filename)). My...
0
1326
by: C. Barnes | last post by:
Summary: Sorts strings in a way that seems natural to humans. If the strings contain integers, then the integers are ordered numerically. For example, sorts into the order . Code:
1
2420
by: Connelly Barnes | last post by:
Summary: Sorts strings in a way that seems natural to humans. If the strings contain integers, then the integers are ordered numerically. For example, sorts into the order . Code: #---------------------------------------------------------
15
7246
by: Twan Kennis | last post by:
Hi, I have a DB2 database on the IBM iSeries platform, on which I created several Stored Procedures with the SQLCODE as a return-parameter. These Stored Procedures are called from a Windows application (build in Visual Basic) using an ADO/OLE DB Provider on a IBM Client Access ODBC driver. On the Internet I found a whitepaper "SQL messages and codes" provided by IBM which describes a complete list of all SQLSTATEs, SQLCODEs and
4
8491
by: sathyashrayan | last post by:
(This is not a home work question) Dear group, I want a program to find one number between a set of natural number.A program to guess a number in between a Natural number set.This should be a simple task but my mind suddenly got stuck. I am trying to implement a square root function as a practice. I am able to code for the perfect square
1
1759
by: Hendri Adriaens | last post by:
Hi, I have an onmouseover script that displays a div with some comment. There are several links getting this onmouseover functionality, all with their own comment text. Now I want the div to have a max width, but if the natural width is smaller than the max width, it should get the natural width. commentObj is the div and commentObj.offsetWidth returns the natural width, as long as we didn't set it to anything else (it seems). As soon as...
1
2633
by: Steven Bird | last post by:
NLTK — the Natural Language Toolkit — is a suite of open source Python modules, data sets and tutorials supporting research and development in natural language processing. It comes with 50k lines of code, 300Mb of datasets, and a 360 page book which teaches both Python and Natural Language Processing. NLTK has been adopted in at least 40 university courses. NLTK is hosted on sourceforge, and is ranked in the top 200 projects. ...
7
1694
by: joproulx | last post by:
Hi, I was wondering if there was a way with Reflection to find dynamically if an object was referencing indirectly another object. A simple example would be: Object1 | --Object2 |
275
12346
by: Astley Le Jasper | last post by:
Sorry for the numpty question ... How do you find the reference name of an object? So if i have this bob = modulename.objectname() how do i find that the name is 'bob'
0
8995
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8832
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9558
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9378
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9331
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
6077
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4608
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
2791
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2216
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.