Improving database structure in one to many relations - mysql

I'm creating a database to keep track on various statistics on my self and I'm wondering if there's a better way to store multiple entries for a single date.
E.g. from my table I have AllergyMedicine which can track multiple medicines taken on the same date, is there a better way to do this?
Also the tables Food and Allergy seems unnecessary, is there a better way to group tables?
Any suggestions are appreciated!

I find it helps to state the problem in a semi structured way, as below.
The system monitors one or more **persons**.
Each person consumes zero or more **items**. Each consumption has an attribute of date and time.
Items can be **food**, or **medicines**.
Food can be of the types **snack**, **fruit** or **meal**.
A meal has a **type**.
A person may report **symptoms**. Each report will cover a period of time, and be reported at a specific date/time.
Symptoms may be associated with zero or more **allergies**.
I do not believe that "date" is an entity in your schema - it's an attribute of events that occur, e.g. consuming something, or noticing a symptom.
If the statements above are true, the schema might be:
Persons
ID
name
...
FoodItemType
ID
Name
FoodItem
ID
Name
FoodItemTypeID (FK)
Medicine
ID
Name
FoodConsumption
PersonID
FoodID
ConsumptionDateTime
MedicineConsumption
PersonID
MedicineID
ConsumptionDateTime
Symptom
ID
Name
....
SymptomObservation
PersonID
SymptomID
SymptomStartDateTime
SymptomEndDateTime
SymptomReportDateTime
Allergy
ID
Name
AllergySymptom
AllergyID
SymptomID

Of course, if you take more than one medicine on one day, why not isolate that day (=date) in its own table?
So you'll have a table "days" with only dates, that you either prefill (like a calendar) or only fill with those days when you really took that medicine.
That way, you save a lot of space by "centering" the date in one table and relating everything else to it. Which is actually a very precise model of reality.
All your "FoodSnack", "FoodMeal", "AllergyMedicine" etc. with a date in them will become plain N:M mapping tables then.
You could even abstract further, reduce tables and make just three tables:
symptoms
causes
treatment
All of those related to the central "day" table (I wouldn't call it "Date", cause that's a keyword and easily mistaken also), plus related to each other, where applicable.

Related

Solving a one-to-one problem in database design

Sorry if this is obvious but I'm new to database design.
A customer must make a reservation before renting an item(s), he provides details up front such as dates of reservation, item type etc. The employee checks if item is available before allowing the customer to rent it. If available he enters item id, rental date, return date, etc into the system.
Am I correct in creating two tables for this? One for Reservations(which includes the proposed rental info.) and one for Rentals (Which includes actual rental info). And If so, wouldn't these have a one to one relationship? How could I get around this one to one relationship? Should I merge the two tables?
Firstly, since a reservation may never materialize as a rental, the relationship is not exactly 1:1 but 1:(0-1).
I would think that it's correct that you model them as separate entities since:
They may have different "life cycles".
They most likely have different properties.
A rental will probably be related to a bunch of other entities compared to a reservation. Those FKs will make sense for rentals but not for reservations.
I might be wrong but from what i'm understanding you can have just 1 table for rentals and have a column named status as enum (0,1) 0 being available and 1 rented. I'm assuming you are not renting the same item at the same time.

Database ER Model weekday availability

I've got a annoying design issue when designing a database and it's models. Essentially, the database got clients and customers which should be able to make appointments with eachother. The clients should have their availability (on a general week basis) stored in the database, and this needs to be added to the appointment model. The solution does not require or want precise hours for the availability, just one value for each day - ranging from "not available", to "maybe available " to "available". The only solution i've come up with so far includes having all 7 days stored in a row for each client, but it looks nasty.
So here's some of what I got so far:
Client model:
ClientId
Service,
Fee
Customer-that-uses-Client model:
CustomerId
ServiceNeed
Availability-model:
ClientID (FK/PK)
Monday, (int)
...
...
Sunday (int)
And finally, appointment model:
AppointmentId
ClientID
CustomerID
StartDate
Hourse
Problem: is there any way i can redesign the avilability model to ... well, need less fields and still get each day stored with a (1-3) value depending on the clients availability ? Would also be really good if the appointment model wouldnt need to reference all that data from the availability model...
Problem
Answering the narrow question is easy. However, noting the Relational Database tag, there are a few problems in your model, that render it somewhat less than Relational.
Eg. the data content in each logical row needs to be unique. (Uniqueness on the Record id, which is physical, system-generated, and not from the data, cannot provide row uniqueness.) The Primary Key must be "made up from the data", which is of course the only way to make the data row unique.
Eg. values such as Day of availability and AvailabilityType are not constrained, and they need to be.
Relational Data Model
With the issues fixed, the answer looks like this:
Notation
All my data models are rendered in IDEF1X, the Standard for modelling Relational databases since 1993.
My IDEF1X Introduction is essential reading for those who are new to the Relational Model or data modelling.
Content
In the Relational Model, there is a large emphasis on constraining the data, such that the database as a whole contains only valid data.
The only solution i've come up with so far includes having all 7 days stored in a row for each client, but it looks nasty.
Yes. What you had was a repeating attribute (they are named Monday..Sunday, which may not look like a repeating attribute, but it is one, no less than a CSV list). That breaks Codd's Second Normal Form.
The solution is to place the single element in a subordinate table ProviderAvailable.
Day of availability and AvailabilityType are now constrained to a set of values.
The rows in Provider (sorry, the use of "Client" in this context grates on me) and Customer are now unique, due to addition of a Name. The users will not use an internal number to identify such entities, they will use a name, usually a ShortName.
Once the model is tightened up, and all the columns are defined, if Name (not a combination of LastName, FirstName, Initial) is unique, you can eliminate the RecordId, and elevate the Name AK to the PK.
Not Modelled
You have not asked, and I have not modelled these items, but I suspect they will come up as you progress in the development.
A Provider (Client) provides 1 Service. There may be more than 1 in future.
A Customer, seeking 1 Service, can make an Appointment with any Provider (who may or may not provide that Service). You may want to constrain each Appointment to a Provider who provides the sought Service.
As per my comment. It depends on how tight you want this Availability/Reservation system to be. Right now, there is nothing to prevent more than one Customer reserving one Provider on a particular Day, ie. a double-booking.
Normalize that availability table: instead of
ClientID (FK/PK)
Monday, (int)
...
...
Sunday (int)
go with
ClientID (PK/FK)
weekday integer value (0-6 or maybe 1-7) (PK)
availability integer value 1-3
This table has a compound primary key, made of (ClientID, weekday) because each client may have either zero or one entry for each of the seven weekdays.
In this table, you might have these rows:
43 2 3 (on Tuesdays = 2, client 43 is Available =3)
43 3 2 (on Wednesdays = 3, client 43 is MaybeAvailable =2)
If the row is missing, it means the client is unavailable. an availability value of 1 also means that.

Attendance System MongoDB design

I need to design and implement a database for employee's attendance system. The db need not to be a non-relational, I can go with whatever suits best with the requirements. The requirements are simple, I need to store employees information along with their clock in and out times.
Data requirements are as follows:
Number of employees will not be big (20-50).
Ability to retrieve all attendance times for all employees for a specific day or range of days (for a month for example).
Ability to add/modify/remove attendance times for specific employees.
Ability to retrieve calculated late attendance for each employee. (Employee is considered late according to some business rules related to attendance times and employee's information).
-Is using MongoDB better that using relational SQL (like mySQL)?
-What's the suggested high level design of the DB that will best simplifies DB implementation, data access, and application development?
This design can be achieved by both MongoDB or a relational database, with strengths and weaknesses of each. The schema design by user641887 is a perfectly valid approach with MongoDB, although I wouldn't use "date" as the "_id" in attendence, as two employees on the same day will have the same "_id" which is invalid, I would leave the "_id" of attendee of an Object_id. However just be aware about the limitations in mongo with collection joins, as you will need to look into the '$lookup' function (https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/), which was only added in Mongo-3.2. The advanatage of a mongo design is that it allows each document in the attendance table that user641887 proposed by be dynamic, and should this database grow very large, it shouldn't be too hard to scale the database. But I doubt that will be a concern if there are only 50 staff with 1 entry per day (50*365 = 18250 per year), even 10 years of data is a very small amount.
The above requirements can also be achieved using a relational structure, where you would again have 2 tables as described by user641887. Depending how many additional pieces of information you want to store in the "other attribute/parameters" you have a couple of options. If there are only a few known possible other attributes, then you can add a few nullable fields to each table. But if there are many fields which could exist or you don't know what to expect before you add them, then you can have two additional tables associated with employee:
employee_attributes:
employee _id : the _id code that matches the employee _id in the
employee table
attribute_code : an integer code that links to the code_description table (below)
attribute_value: the value of the attribute
NOTE: This approach with a single attribute table is limited to the attribute_value only having one data type (most likely string), but if you need to have multiple data types you can resolve that by having multiple employee attribute tables for each data type, e.g. employee_attribute_i (for ints), employee_attribute_s (for strings), employee_attribute_b (for booleans).
attribute_code_description:
attribute_code : the int code of this attribute
attribute_meaning: a string description of what this attribute is for (e.g. "allergies", "probation", "start_time", ...)
This same approach can be used for the "other attendance parameters".
With regards to "calculated late attendance for each employee", then you can set up triggers/rules to automatically fire that can add to a counter for each employee to monitor if they are late. This will work by firing a trigger upon insert into the the attendee table where the in_time field that can then by compared with the employees "start_time", if it is greater that that, +1 to a counter that logs how often they are late. I know that can be done in several relational databases (postgres/ingres certainly, and I'm sure many others). I don't know if that can be done on a mongo server.
you could have 2 collections one for the employee and one for the attendance.
employee collection can have attributes related to the employee
_id : Object_id
name : string
email : string
... other employee attributes
and attendance collection can have attributes related to attendance.
_id : date (you can store date as string or any other format to make it unique per day
in_time : date
out_time : date
other attendance parameters....
employee_id : (_id for employee)
HTH.

Relational Database: Variable Fields

I am making this hotel reservation program and i'm in a dilemma.
I have the users table that is basically
id
identifier
password
realName
cellphone
email
The rooms table
id
type
price
And the reservations table
id
checkin
checkout
room_id
nights
total_cost
The problem is that a single user in a single reservation can ask for multiple rooms with multiple check ins and outs.
What would be the best approach to achieve this? I was thinking of splitting the various rooms with different reservation ids and then make some kind of workaround to relation them.
I think your data structure is fine as far as it goes. You have two choices.
The first is to relax your language. Don't say that "a single user in a single reservation can ask for multiple rooms with multiple check ins and outs". Instead say, "a single user can make multiple reservations at the same time". Just changing this language fixes your conundrum.
If you really have to tie things together, I might suggest having an column that groups reservations made by a single user together. This could be a full-blown entity, which would have a foreign key reference to another table. Or, it could simply be an identifier, such as the first reservation in the series or the user id with a date/time stamp. I'm not sure that a full blown entity is needed, but you might find it useful.

Questions on Auction Database Schema

I was looking at the following db model and I had some questions on it. I'm sure it's a good design as the guy behind it seems to be reasonably well qualified, although some things don't make sense:
Why's he seperated out bidders and sellers? I thought you'd have users, and users can place bids and sell items. You'd have a bids table with a reference to user, and a auctions table, with reference to user table. He talks a lot in his tutorials about making sure models are scalable and ready for change (don't have a status column for instance, have statuses in another table and reference that) so what's up here?
Why are their fields like "planned close date" and "winner". Isn't this data duplication, as the planned close date could be calculated using the last bid time (for acutions that use auto extend) and the winner is simply the last bid when the auction closes..?
FYI: I'm trying to build my own auction site in PHP/MySQL from scratch and it's proving to be quite difficult, so tutorials on this would be great!
Thanks!
Why's he seperated out bidders and sellers?
Each table has unique columns specific to each one, so he keeps them separate. I would actually go with user and sub-type bidder and seller to the user, like:
TABLE User (UserID (PK), ... all common fields for any user)
TABLE Bidder (UserID (PK,FK) ... all fields specific to bidders)
TABLE Seller (UserID (PK,FK) ... all fields specific to sellers)
Concerning "planned close date" and "winner":
Yes, it is data duplication, but in some cases you have to live with that in order to scale properly.
Of course you can use the last bid time from the "Bids" table to calculate the close date of the auction, but if your site gets really big, you don't want to calculate this every time someone loads the "auctions ending soon" list - because you have to calculate it for every single active auction, every time, just to find the few ones that are ending soon.
(and this list will get loaded a lot, believe me!).
Same with the winner - it's just faster to load if you have the information in the auctions
table, so you don't always have to join the "Bids" table and get the user from the last bid of every auction.
Think of the page in "My eBay" which shows all the auctions you won in the last 60 days - you would have to search all the bids of all auctions for the winner every single time someone loads this list!
A perfectly normalized database isn't always the best solution if you expect it to scale with lots of users.