Database design for flagging system - sql

I have a database which captures information relating to a patient for a medical practice. This information is spread across several tables:
Patient - For contact information
PatientMedicalHistory - For medical conditions unrelated to the current problem
PatientEpisode - Financial information for the current visit
PatientEpisodeReason - Stuff relating to why the patient is here today
I want to introduce a flag system, so that any messages will appear when bringing up the patient details. So for example, if the patient has had a heart attack previously this would need to be flagged (that info would be in PatientMedicalHistory).
My current approach is to set up a flag lookup table which defines the flag type, and the table/column that the flag is referring to and what the value would be in order to raise that flag:
CREATE TABLE FlagType
(
ID INT PRIMARY KEY IDENTITY,
TypeName NVARCHAR(300) NOT NULL,
Colour NVARCHAR(100) NOT NULL,
Urgency INT NOT NULL
)
CREATE TABLE Flag
(
ID INT PRIMARY KEY IDENTITY,
FlagTypeID INT NOT NULL REFERENCES FlagType(ID),
TableName NVARCHAR(300) NOT NULL,
FieldName NVARCHAR(300) NOT NULL,
FlagValue NVARCHAR(300) NOT NULL
)
This seemed all very well, but then trying to write either a) a stored procedure that doesn't resemble a mess or b) a LINQ query that doesn't kill performance seems difficult.
Is there any alternatives to this? The issue is that the flag could be defined on any column in any of the tables above. This totals about 80 columns in total.

You can add three fields to PatientMedicalHistory table: organ, disease, criticality.
When a patient comes in with a problem, you can pull patient history based on the same organ or disease presented in the current episode where the criticality meets a certain threshold. What you are doing here is classifying your patient history data so it relates to the current episode data.

Related

Oracle SQL: Foreign key from three possible tables?

Take the following scenario:
CREATE TABLE customers (
cust_num INTEGER PRIMARY KEY,
cust_name VARCHAR(60) NOT NULL,
//other info
);
CREATE TABLE checking_account (
acc_num NUMBER(16) NOT NULL,
acc_type VARCHAR(8) NOT NULL,
//other info
);
CREATE TABLE savings_account (
acc_num NUMBER(16) NOT NULL,
acc_type VARCHAR(8) NOT NULL,
//other info
);
CREATE TABLE loan_account (
acc_num NUMBER(16) NOT NULL,
acc_type VARCHAR(8) NOT NULL,
//other info
);
CREATE TABLE has_account (
acc_num NUMBER(16) NOT NULL,
acc_type VARCHAR(8) NOT NULL,
cust_num INTEGER
);
More than one customer may have the same account and additionally, one customer may have multiple accounts. The account number in the has_account table may or may not be unique across accounts.
How could this be represented? I have tried to implement class table inheritance and concrete inheritance but I can't figure out how to allow one account number to be shared across multiple accounts. I have yet to find an example or explanation which makes this consideration. Could anybody give me an insight as to how to achieve this functionality or at least point me in the right direction? Any help is greatly appreciated
'customers' table is your primary table which should be linked with all 3 tables 'checking_account','savings_account' and 'loan_account'.In these 3 table there should be one column cust_num which will represent forign key.
So if customer has saving account and loan account then for this customer there is 2 row in customers table and one-one row in savings_account & loan_account table.
Customer all account info should be in has_account table where cust_num is forign key so you can easily find customer info with his account details via join on customer & has_account table.
If you want to know one customer has how many account then use count(cust_num) in your customers table.
Note - If you follow good DB design then you should have only one table called as 'cust_account' in which columns should be like acc_num,acc_code,acc_name etc and acc_type column should be updated with valid value like 'saving','loan' or 'checking'.
In your table structure acc_type column is given for all 3 account type tables which has no sense if you have different table for different account type.Remove this column if you are going to use seprate table for account type otherwise use one table with column acc_type.
Not a complete answer and too long for a comment but I thought I'd address some of your reasons why you have three separate tables:
"checking account doesn't have an interest rate"
This is a business rule and should not be implemented by a different table structure. Also, in times of higher interest rates it's certainly plausible for a checking account to earn interest. Business rules are usually much easier to change that data structures.
a loan account doesn't have a balance
Again, this is a business rule - but certainly a loan has a principle balance.
one account number may be shared across multiple account types ... account number would need to be a primary key in which case it couldn't be shared across accounts
One way to solve that is to use account number , account type as a "logical" compound primary key (note that in most DB systems there are benefits to using a sequence number as a "true" primary key that is independent of the actual record information. What if an account number changes for some reason?
If there are attributes of one account type that cannot feasibly stored in a "shared" data model, then you could model those as sub-tables:
|- 0:1 -- 0:1 CheckingAccount
Customer 1--* Account -|- 0:1 -- 0:1 SavingsAccount
|- 0:1 -- 0:1 LoanAccount
But you may find that you end up with similar problem that are more easily solved using business rules that separate data structures.
Create custReg table which have parent-child relationship of account types between column data. That column named accountID would be PK. As common attributes can easily be placed in single table.
Further tables with different attributes can be created and subsequently linked with theirs account ID at first-child level.
Then use hierarchical queries to access data between tables.

Normalizing a table with duplicate rows and many-to-many relationships

I am designing the database for an accounting system, currently working on the Expenses table.
According to IRS rules, whenever you update a row in any accounting table, you need to cancel out the existing row by negating its values, and create a new row with the modified information, like so:
Set the row's Status flag to "Modified"
Create an identical copy of this row, with all Money fields negated, so that the sum of the two rows is 0
Create a 3rd row, identical to the first one, with the modified data
Each expense has an identity field called ID for internal identification purposes, and an ExpenseID field, which identifies the transaction to the users. The two cannot be the same, because
ExpenseID can be repeated twice if the transaction was modified and its row was duplicated.
ExpenseIDs MUST be consecutive and NEVER have gaps, while identity fields can skip numbers if a transaction is rolled back and the identity is not reseeded.
In general, I believe the primary key should have no business meaning whatsoever.
My problem is that there are other tables used to link these expenses Many-To-Many to other objects in our system. E.g.: each expense can be linked to documents, folders, users, etc.
So it looks something like this:
create table Expenses (
ID int not null identity(1,1),
ExpenseID int not null,
Amount Money not null,
Status tinyint not null,
[...]
)
create table Expenses_Users (
ExpenseID int not null,
UserID int not null
)
alter table Expenses_Users add constraint FK_Expenses_Users_Expenses
foreign key (ExpenseID) references Expenses (ID)
alter table Expenses_Users add constraint FK_Expenses_Users_Users
foreign key (UserID) references Users (ID)
Now, because of the IRS guidelines, I have to duplicate not only rows in the Expenses table, but also in Expenses_Users, and any other table that links Expenses to other tables.
I have two ideas on how to solve this:
Option One: Normalize Expenses like this:
create table Expenses (
ID int not null identity(1,1),
ExpenseID int not null,
Status tinyint not null,
[...]
)
create table ExpensesNormalized (
ExpenseID int not null,
Amount Money not null
)
alter table ExpensesNormalized add constraint FK_ExpensesNormalized_Expenses
foreign key (ExpenseID) references Expenses(ExpenseID)
This means I'll only have to link external tables to Expenses, not ExpensesNormalized. Also, when updating an expense, I'll only duplicate and negate the data in ExpensesNormalized, which means I'll have far less redundant data in the Expenses table.
However, I'll have to use a JOIN clause every single time I SELECT from Expenses. I fear a performance hit because of this.
Option Two: Use the same tables I use now, but have the field Expenses_Users.ExpenseID point to the field Expenses.ExpenseID. This means that I won't have to duplicate any external objects because they'll point to ExpenseID, which may occur several times.
However, this will not be a real foreign key because SQL Server does not allow foreign keys to non-unique fields, so I'll have to implement foreign key logic in a trigger.
I'm having a hard time deciding between these two options. Any feedback would be appreciated.

Can a table title be a Primary Key?

I'm trying to retrofit some tables to an existing database. The existing database has equipment numbers and I'm trying to add in tables with more information on that equipment. Ideally, I'd like to make the table titles the ID numbers and set those as the PK of that table, making the ID numbers in the equipment list the FK.
Is it possible to set the table title as the PK? Here's an example of one of the tables, and I'd like to make "E0111" the PK.
CREATE TABLE E0111(
EQUIPMENT Varchar(200),
MAINTENANCE varchar(200),
CYCLE varchar(200)
);
No you can't do this because the primary key needs to be unique for every row of your table. If you "could" use the table name as the primary key it would be the same for every row.
You should use a unique column in your table as the primary key.
Also, I have no idea how you could achieve this with SQLite or any DBMS.
First thing before I even get anywhere near answering the question about the table names being primary keys, we need to take a step back.
You should NOT have a table for each piece of equipment.
You need an Equipment table, that will store all of your pieces of Equipment together. I assume you have that already in the existing database.
Hopefully it is keyed with a Unique Identifier AND an Equipment Number. The reason for having a separate Unique Identifier, is that your database server uses this for referential integrity and performance - this is not a value that you should show or use anywhere other than inside the database and between your database and whatever application you are using to modify the database. It should not typically be shown to the user.
The Equipment Number is the one you are familiar with (ie 'E0111'), because this is shown to the User and marked on reports etc. The two have different purposes and needs, so should not be combined into a single value.
I will take a stab at what your Equipment table may look like:
EquipmentId int -- database Id - used for primary key
EquipmentName Varchar(200) -- human readable
EquipmentDescription Text
PurchaseDate DateTime
SerialNumber VarChar(50)
Model Varchar(200)
etc..
To then add the Maintenance Cycle table as you propose above it would look like:
MaintenanceId int -- database Id - used for primary key this time for the maintenance table.
EquipmentId int -- foreign key - references the equipment table
MaintenanceType Varchar(200)
DatePerformed DateTime
MaintenanceResults VarChar(200)
NextMaintenanceDate DateTime
To get the results about the Maintenance Cycle for all equipment, you then JOIN the tables on the 2 EquipmentIds, ie
SELECT EquipmentName, EquipmentDescription, SerialNumber, MaintenanceType DatePerformed
FROM Equipment
JOIN MaintenanceCycle ON Equipment.EquipmentId = Maintenance.EquipmentId
WHERE EquipmentName = 'E0111'
You cannot make the name of the table a primary key.
All primary keys should be unique and a table column not table name. This is the general rule of thumb for a priamry key. There are plenty of resources on the internet about Primary keys.
Here are just afew:
http://www.w3schools.com/sql/sql_primarykey.asp
http://database-programmer.blogspot.co.uk/2008/01/database-skills-sane-approach-to.html
The name of a table should be descriptive of what is hold within it. See that data table as a drawer where you shall label what it contains.
In my humble point of view, the ID of an equipement shall only be labeled as-is on the equipement in question. Otherwise, in your database, it shall be the table Equipments that prevails with the ID of each piece of equipment you have.
Then, if you have other equipment-related information to save, add another table with the kind of information it shall contains, with the ID of the related equipment for which this information is saved.
For example, let's say we hold a maintenance schedule over your equipment.
Equipments
-----------------------------------------------------
Id | Description | Location | Brand | Model
-----------------------------------------------------
1 | Printer/Copier| 1st Floor | HP | PSC1000
Maintenances
---------------------------------------------------------
Id | Description | Date | EquipmentId | EmployeeId
---------------------------------------------------------
Note that the EmployeeId column shall be there only if one requires to know who did what maintenance and when, for instance.
MaintenanceCycles
--------------------------------------------
Id | Code | Description | EquipementId
--------------------------------------------
1 | M | Monthly | 1
This way, every equipment can have its cycle, and even multiple cycles per equipment if required. This lets you the flexibility that you need for further changes.

SQL - NULL foreign key

Please have a look at the database design below:
create table Person (id int identity, InvoiceID int not null)
create table Invoice (id int identity, date datetime)
Currently all persons have an invoiceID i.e. the InvoiceID is not null.
I want to extend the database so that some person does not have an Invoice. The original developer hated nulls and never uses them. I want to be consistent so I am wondering if there are other patterns I can use to extend the database to meet this requirement. How can this be approached without using nulls?
Please note that the two tables above are for illustration purposes. They are not the actual tables.
NULL is a very important feature in databases and programming in general. It is significantly different from being zero or any other value. It is most commonly used to signify absence of value (though it also can mean unknown value, but that's less used as the interpretation). If some people do not have an invoice, then you should truly allow NULL, as that matches your desired Schema
A common pattern would be to store that association in a separate table.
Person: Id
Invoice: Id
Assoc: person_id, assoc_id
Then if a person doesn't have an invoice, you simply don't have a row. This approach also allows a person to have more than one invoice id which might make sense.
The only way to represent the optional relationship while avoiding nulls is to use another table, as some other answers have suggested. Then the absence of a row for a given Person indicates the person has no Invoice. You can enforce a 1:1 relationship between this table and the Person table by making person_id be the primary or unique key:
CREATE TABLE PersonInvoice (
person_id INT NOT NULL PRIMARY KEY,
invoice_id INT NOT NULL,
FOREIGN KEY (person_id) REFERENCES Person(id),
FOREIGN KEY (invoice_id) REFERENCES Invoice(id)
);
If you want to permit each person to have multiple invoices, you can declare the primary key as the pair of columns instead.
But this solution is to meet your requirement to avoid NULL. This is an artificial requirement. NULL has a legitimate place in a data model.
Some relational database theorists like Chris Date eschew NULL, explaining that the existence of NULL leads to some troubling logical anomalies in relational logic. For this camp, the absence of a row as shown above is a better way to represent missing data.
But other theorists, including E. F. Codd who wrote the seminal paper on relational theory, acknowledged the importance of a placeholder that means either "not known" or "not applicable." Codd even proposed in a 1990 book that SQL needed two placeholders, one for "missing but applicable" (i.e. unknown), and the other for "missing but inapplicable."
To me, the anomalies we see when using NULL in certain ways are like the undefined results we see in arithmetic when we divide by zero. The solution is: don't do that.
But certainly we shouldn't use any non-NULL value like 0 or '' (empty string) to represent missing data. And likewise we shouldn't use a NULL as if it were an ordinary scalar value.
I wrote more about NULL in a chapter titled "Fear of the Unknown" in my book, SQL Antipatterns Volume 1: Avoiding the Pitfalls of Database Programming.
You need to move the invoice/person relation to another table.
You end up with
create table Person (id int person_identity)
create table PersonInvoice (id int person_id, InvoiceID int not null)
create table Invoice (id int identity, date datetime)
You need this for some databases to allow in InvoiceId to be a foreign key as some do not allow NULLS in a foreign key.
If a person only can have one invoice then PersonInvoice can have a unique constraint on the person_id as well as the two columns together. You can also enforce having a single person for a invoice by adding a unique constraint to the invoiceID field.

SQL Design: need ability to add custom "columns" to a table using a fixed schema

Using: SQL Server 2008, Entity Framework, WCF 4 REST
I have a table for holding the measurement data generated by monitoring system (aka the app). There are currently about 10 different well-known pieces of data being monitored within the app - and each corresponds to a column in the table. Each customer can "customize" each of their apps to capture from 1 to 10 pieces of data - they only need to capture those pieces of info they are interested in analyzing. Everything's working great (and performance is good) with this straight-forward fixed schema. This schema is designed to be multi-tenant, so multiple applications across multiple customers in multiple locations could be pumping data into the same DB - millions and millions of rows of measurement data (I wouldn't be surprised if we go to Azure before too long).
I have now been told that the measurement application will soon be able to monitor additional "things". This new list (so far I'm told is at around 150 items) could wind up being about 1000 items being measured. Add on top of that, the user could specify their own criteria for items to monitor/measure (i.e. custom measurements equating to custom columns.) The good news is that all the measurement data will be integers.
Now the fun - how do I design the schema for this situation? I would really like to keep the schema fixed. I would also like to keep it as performant as possible given the high volumes of data.
Any help is appreciated.
Current Schema:
CREATE TABLE MeasurementData (
DataId bigint IDENTITY(1,1) NOT NULL PRIMARY KEY,
ApplicationId int NOT NULL, -- FK to Application table
DateCollected datetime NOT NULL,
Length int NULL,
Width int NULL,
Height int NULL,
Color int NULL,
Shape int NULL,
Mass int NULL
)
CREATE TABLE Application (
ApplicationId int IDENTITY(1,1) NOT NULL PRIMARY KEY,
CompanyId int NOT NULL, -- FK to Company table
SerialNumber nvarchar(50) NOT NULL
)
CREATE TABLE Company (
CompanyId int IDENTITY(1,1) NOT NULL PRIMARY KEY,
CompanyName nvarchar(50) NOT NULL
)
And then we have the user table, the roles table, etc, where there's a 1-n relationship btw company and user.
FYI, the web app will then present the data with tables, graphs, etc (communicating via the REST web service layer)
Can you add two more tables? One with the types of measurements and the other with a mapping from the type to the measurement itself?
Basically A table with {DataId, DataMeasurementTypeId, DataValue} and {DataMeasurementTypeId, DataMeasurementType}
That should allow you to provide stored procedures to retrieve all Datameasurements in a table.
The better optiom might be to solve it with a Name,Value table and have the business object layer take care of constructing the right content.. That would fit (and likely perform) better with BigTable approach of Google than RDBMS though.
Take a look at these SO examples: one, two, three.