How to normalize a database schema - database

I have two tables:
customer (
client_id(PK),
lastname,
firstname,
flightID (Fk)
)
flight (
flight_id(PK),
flightarrival,
flightdepart
)
My questions are:
Are there any problems with the schema?
How can I add data to the flight table?
I really want to separate the two because bulk tables are confusing.
Here is an example of a "bulk table":
customer(
client_id(PK),
lastname,
firstname,
flightarrival,
flightdepart
)
but I want to normalize it and separate it from the customer table and just link them.

The schema you proposed would mean that each customer could be related to one (not zero, not more than one) flight, which feels wrong.
In essence, I think you have a many-to-many relationship, which you can do with three tables:
customer (id(PK), lastname, firstname)
flight (id(PK), flightarrival, flightdepart)
customer_flight (
customer_id REFERENCES customer(id),
flight_id REFERENCES flight(id)
)

You should create a separate cross-reference many-tomany - table which will be like
customer_flights(id int (pk),customer_id int, flight_id int,timecreated(optional))
one customer may have several flights booked like in past and in future...
and later join the two tables basing on the records in this table

Related

What's better in designing object attachment in sql server

I need to represent adding attachments to order or order item using sql server.
I think of two ways but wonder which one is better.
Solution 1:
table1: attachment (id, name, description, uri, ...)
table2: order (id, client_id, ...)
table3: orderItem (id, order_id, product_id, ...)
table2: objectAttachment (id, objectType, object_id, attachment_id, ...)
In this case I retrieved order attachments like this:
create proc GetOrderAttachments(#order_id int)
AS
select attachment_name, attachment_uri, attachment_desription, order.(...)
from objectAttachment orderAttachment
inner join order on order.id = orderAttachment.object_id
inner join attachment on attachment.id = orderAttachment.attachment_id
where orderAttachment.objectType = 'order' and orderAttachment.object_id = #order_id
Solution 2:
table1: attachment (id, name, description, uri, ...)
table2: orderAttachment (id, order_id, orderItem_id, ...)
table3: order (id, client_id, ...)
table4: orderItem (id, order_id, product_id, ...)
In this case I retrieved order attachments like this (knowing that orderItem_id is neglected):
create proc GetOrderAttachments(#order_id int)
AS
select attachment_name, attachment_uri, attachment_desription, order.(...)
from orderAttachment orderAttachment
inner join order on order.id = orderAttachment.order_id
inner join attachment on attachment.id = orderAttachment.attachment_id and orderAttachment.order_id = #order_id
Lets consider various situations and compare each approach.
Question. How many attachment are there of any type?
1 approach will select from one table(good).
2 approach will need to union many tables.
What if you add one more entity with attachments. You will need to remember all places where you are answering questions like this and add one more case. First approach is safe from this point of view.
You are asked to add additional attributes for order attachments and some other attributes for some other entity's attachments.
With first approach you will need to add attributes of both in one table which will be nullable and filled for just one type of entity type.
Second approach is safe. You add attributes to appropriate entities. There are no many many nullable columns just to maintain one type of attachment.
You are asked to delete all attachments of orders.
With first approach if you have huge amount of data delete operation will take long period of time.
With second approach you can remove relationships and truncate table which will take millisecond.
You can continue this list. Answering various questions and considering cons and pros of different approaches will help you to decide which approach fits better to your needs. There wouldn't be just one correct answer.
There is no better solution. All depends on your needs. The problem here is which table inheritance model fits for you.
You can start reading here:
Single Table Inheritance
Class Table Inheritance
Concrete Table Inheritance
Single Table Inheritance
Class Table Inheritance
*ttp://martinfowler.com/eaaCatalog/concreteTableInheritance.html

SQL Server : database design - composite primary key

I need your suggestion on how to implement SQL Server table relationships.
I have many customers, each holds a unique id (customerID)
each customer can have many categories associated (categoryID)
each customer can have many sub categories (subCategoryID) for
when a customer logs in I know its CustomerID, CategoryID and SubCategoryID.
customer plans in advance how many hours will work every week for the year to come (on december
2014 plans 52 weeks of 2015)
every day a customer reports if they worked or took a day off.
I thought of having a table called WeeklyPlanning with columns:
CustomerID, CategoryID, SubCategoryID, Year, WeekNumber, WorkingHoursPlan
and another table called DailyWorkingHours with columns:
Dates, WorkingHours
My questions:
I don't know how to combine these two tables together, use a compound key? (CustomerID, CategoryID, SubCategoryID, Year, WeekNumber) or maybe generate a unique PK in WeeklyPlanning that will be used as a FK in DailyWorkingHours?
I'm looking for the best way to implement this.
thanks
Do you really want to specify FIVE column's values for each JOIN between those two tables? That's what you'll have to do if you have a compound primary key made up from five columns - you need all those columns in your child table as well, and you need to always specify all five columns when doing a JOIN ..... ouch ......
If not - use a surrogate column in WeeklyPlanning (a WeeklyPlanningID INT IDENTITY(1,1)) to simplify your life significantly!

Join tables with 'condition' in RDBMS

I have 3 tables:
Persons(PersonID, PersonName, PersonAge, PersonType)
Students(StudentID (fk to Persons.PersonID), StudentRank, StudentClassID, ...)
Teachers(TeacherID (fk to Persons.PersonID), TeacherSalary, ...)
A person can be only one type: student or teacher. So if I want to list all person with the type (student or teacher), I need to check PersonType of Persons table, then join with corresponding table (Students, Teachers)? Is it good enough? Anyone can give me a better solution?
Edit: I use combo: PHP + MySQL.
Update: Structure of tables.
The...
SELECT * FROM Persons JOIN Students ON Persons.PersonID = Students.StudentID
...will not return any teachers.
So you don't have to filter on PersonType (but may want to in more complex cases, if it's indexed in a way that aids performance).
--- EDIT ---
OK, so you want to "cram" everything together then sort on PersonName. You can do that by carefully filling the "gaps" between two child tables with NULLs:
SELECT *
FROM (
SELECT Persons.*, StudentRank, StudentClassID, NULL TeacherSalary
FROM Persons JOIN Students ON Persons.PersonID = Students.StudentID
UNION ALL
SELECT Persons.*, NULL StudentRank, NULL StudentClassID, TeacherSalary
FROM Persons JOIN Teachers ON Persons.PersonID = Teachers.TeacherID
) Q
ORDER BY PersonName
There are two techniques that will help you, they are explained in the info tab under
class-table-inheritance
shared-primary-key
Your current design reflects much of class table inheritance. What shared primary key will buy you
is the ability to enforce the one to one nature of the relationship between students and persons, and between teachers and persons. It will not enforce a mutually exclusive relationship between teachers and students.
With two joins and a union, you can combine these three tables into a view that captures all this data, with NULLs in places that are not applicable.
You can use find_in_set than u need not to join the two tables:
select p.Personname
from students s,persons p
where find_in_set(s.Studentid,p.Personid)

Database tables: One-to-many of different types

Due to non-disclosure at my work, I have created an analogy of the situation. Please try to focus on the problem and not "Why don't you rename this table, m,erge those tables etc". Because the actual problem is much more complex.
Heres the deal,
Lets say I have a "Employee Pay Rise" record that has to be approved.
There is a table with single "Users".
There are tables that group Users together, forexample, "Managers", "Executives", "Payroll", "Finance". These groupings are different types with different properties.
When creating a "PayRise" record, the user who is creating the record also selects both a number of these groups (managers, executives etc) and/or single users who can 'approve' the pay rise.
What is the best way to relate a single "EmployeePayRise" record to 0 or more user records, and 0 or more of each of the groupings.
I would assume that the users are linked to the groups? If so in this case I would just link the employeePayRise record to one user that it applies to and the user that can approve. So basically you'd have two columns representing this. The EmployeePayRise.employeeId and EmployeePayRise.approvalById columns. If you need to get to groups, you'd join the EmployeePayRise.employeeId = Employee.id records. Keep it simple without over-complicating your design.
My first thought was to create a table that relates individual approvers to pay rise rows.
create table pay_rise_approvers (
pay_rise_id integer not null references some_other_pay_rise_table (pay_rise_id),
pay_rise_approver_id integer not null references users (user_id),
primary key (pay_rise_id, pay_rise_approver_id)
);
You can't have good foreign keys that reference managers sometimes, and reference payroll some other times. Users seems the logical target for the foreign key.
If the person creating the pay rise rows (not shown) chooses managers, then the user interface is responsible for inserting one row per manager into this table. That part's easy.
A person that appears in more than one group might be a problem. I can imagine a vice-president appearing in both "Executive" and "Finance" groups. I don't think that's particularly hard to handle, but it does require some forethought. Suppose the person who entered the data changed her mind, and decided to remove all the executives from the table. Should an executive who's also in finance be removed?
Another problem is that there's a pretty good chance that not every user should be allowed to approve a pay rise. I'd give some thought to that before implementing any solution.
I know it looks ugly but I think somethimes the solution can be to have the table_name in the table and a union query
create table approve_pay_rise (
rise_proposal varchar2(10) -- foreign key to payrise table
, approver varchar2(10) -- key of record in table named in other_table
, other_table varchar2(15) );
insert into approve_pay_rise values ('prop000001', 'e0009999', 'USERS');
insert into approve_pay_rise values ('prop000001', 'm0002200', 'MANAGERS');
Then either in code a case statement, repeated statements for each other_table value (select ... where other_table = '' .. select ... where other_table = '') or a union select.
I have to admit I shudder when I encounter it and I'll now go wash my hands after typing a recomendation to do it, but it works.
Sounds like you'd might need two tables ("ApprovalUsers" and "ApprovalGroups"). The SELECT statement(s) would be a UNION of UserIds from the "ApprovalUsers" and the UserIDs from any other groups of users that are the "ApprovalGroups" related to the PayRiseId.
SELECT UserID
INTO #TempApprovers
FROM ApprovalUsers
WHERE PayRiseId = 12345
IF EXISTS (SELECT GroupName FROM ApprovalGroups WHERE GroupName = "Executives" and PayRiseId = 12345)
BEGIN
SELECT UserID
INTO #TempApprovers
FROM Executives
END
....
EDIT: this would/could duplicate UserIds, so you would probably want to GROUP BY UserID (i.e. SELECT UserID FROM #TempApprovers GROUP BY UserID)

normalization of reservation database

hi im developing a online reservation of a event place my issue is in the module of ticketing if a client booked two functionroom in one ticket im not sure with my database if it is full normalized i just want to be sure please leave comment for database improvement
create table RESERVATIONS (
PK reservation_id
lname,
fname,
contact,
email,
date,
timeStart,
timeEnd
numGuest,
total)
create table FUNCTIONROOMS (
PK function_id,
FK functionroom_id,
FK reservation_id)
create table FUNCTIONROOMDETAILS(
PK functionroom_id,
functionName,
functionPrice,
functionStatus)
im planning for this query is my database normalized? or not
select functionRoom.functionRoom_id
from reservations, functionRoom
where reservation.reservation_id = functionRoom.reservation_id
and reservation_id = 'reservation_id'
Your tables doesn't seem to be normalized, there is no apparent primary key in Reservation.
Normalization is quite a topic, and there are several levels of normal forms, you can use just the ones you need.
And as Jim Garrison said in the comments queries can't be normalized, so your last question doesn't have a clear answer.

Resources