Breaking down model into sql tables issue - mysql

and each customer have basic info (name, age, address) and can have few solutions that the website offers, currently there is only 1 maybe it will be 2 or 3 in the future (not something that will be big).
the one solution that currently the website offers is:
PaymentSolution
Now PaymentSolution have its own services:
PersonalPaymentService
OfficePaymentService
both of those services have active parameter that can be true/false
and for each service there are 3 payment options that can also be active true/false
For example:
PersonalPaymentService(active true)
paymentType startPaymentDate(date value) finishPaymentData(date value) active(boolean)
apartment payment 1/1/2018 1/1/2019 true
car payment 1/1/2018 1/1/2019 true
jetSki payment 1/1/2018 1/1/2019 false
OfficePaymentService(active false)
paymentType startPaymentDate(date value) finishPaymentData(date value) active(boolean) contactEmail(string value)
office payment 1/1/2018 1/1/2019 true john#rentOffice.com
computers payment 1/1/2018 1/1/2019 false john#rentComputers.com
Im trying to figure out how to model such information structure to sql tables, can someone please offer some directions please?
im having hard time how to break this into the right relations and having this model able to scale to more solutions in the future
queries I want to be able tp perform are something like:
give me PersonalPaymentService data for customer id 35.
give me OfficePaymentService for account id 43.
give me all data for customer id 67
anything can help! thanks!

I think you should revisit your design, based on your comment,
for example give me all PersonalPaymentService data for customer id
35. or give me OfficePaymentService for account id 43...or of course give me all data for customer id 67
I think the PersonalPaymentService and OfficePaymentService are logical representation of data and your actual payments are only the 6 types you described.
If you want to keep your tables clean and if you are using your mysql as a datastore, I would say just create a table like
CustomerID, PaymentType, StartPaymentDate, EndPaymentDate
where the PaymentType belongs to only the 6 subtypes.
and use your logical programming (PHP, Java whatever) to categorize the payments into office and personal types.
The advantage of using this schema is that in future if you decide to introduce another payment type, you will not require any schema changes.
However, if your constraint is that SQL should answer your queries whether its personal or office payment, you could theoretically introduce another type (column) called PaymentCategory, which has personal or office payment.

As mentioned in other post, Creating one table and adding a type discriminator column to that table would be the better approach for now . Also writing queries against one table would be easy . There are some situations when you have to add new types with some data(columns) specific to that type in your case column like contactEmail and later you could end up with a table with lot of columns and most of them have null values.
In those type of situations creating a one table(PaymentService) with common columns and creating separate table for each type(PersonalPayment,OfficePayment etc.. ) then adding foreign key constraint to maintain one to one relationship with the common table and each type tables could be a better solution.Writing queries against is not easy compare to previous approach and which requires to join type table with the common table.
Other option is to create separate tables for each type.

Related

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.

Database design: Managing old and new data in database table

I have a table Student with field as followed,
Student table (one record per student)
student_id
Name
Parent_Name
Address_line1, Address_line2, Addess_line
Photo_path
Signature_file_path
Preferred_examcity_choice1,Preferred_examcity_choice1, Preferred_examcity_choice3
Gender
Nationality
.
.
.
I am inserting into this table on Registration form completion through the web interface.
Now there is one more module in a web interface for updating the student data, on every update request I am updating the student table records and inserting the new entry in student_data_change_request. student can change records any number of times.
student_data_change_request
request_id(auto_incr PK)
old_name
new_name
old_photo_path
new_photo_path
old_signature_file_path
new_signature_file_path
Now coming to problem, earlier students were allowed to change very few fields, now client want to allow the candidate to update more number of fields(around 20 fields) and adding old and new columns for the corresponding column isn't elegant and preferred(I guess), I will end up creating 40 columns to keep track of 20 columns. So how should I redesign my table? suggestions are welcomed.
One approach is to have a shadow table named (table)_xx that has the same columns, the time, date, update/insert/delete flag, user or whatever and no referential integrity. Set a trigger to update that table from the source whenever anything happens.
If you've got genuine business requirements that need history then do those properly but this pattern is great as a general audit, debugging and forensic tool.
It's also really easy to automate/script as you just generate it from the DB metadata.
Usually historical table looks like:
request_id
column_name
old_value
new_value
dt
request_id and column_name are primary key. When you update student table you insert new entry in student_data_change_request for each updating column.
Edited:
Another way:
request_id
value_type
name
photo_path
signature_file_path
...
and insert first entry with old values and second entry with new values. Colum value_type is mark old or new.
I would rather have just one table, with an additional column for effective date. Then a view that picks up just the most recent row for each student_id becomes your first "table". If for some reason you must show "current" and "most recently changed" values side-by-side, that is another view.
As usual, it all depends on how you intend to use the data.
My strong preference in these cases is the solution #mathguy suggests - embedding the concept of time in the main table design. This allows you to ask the question "what was this student's address on 1 Jan?", or "who had signature x on 12 Feb?".
If you have to report or execute business logic that reflects the status at any point in time, this design works really well. For instance, if you have to report on how many students lived in a particular address for a given term, you want to know when the records were valid.
But not all applications care about "time" - sometimes, you just want to have an audit table, so you can trace what happened over time in case of anomalies.
In that case, #loztinspace's solution is useful - but in my experience, this rapidly escalates into more work, because those who want to inspect the audit records can or should not get access to a SQL prompt on your production environment.

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.

Sap Unique Employee number

We are using an older version of SAP and don't have access to the database itself.
The version is SAP ECC 6.0.
Can anyone tell me where I can find a unique employee Id/ number for an employee?
SAP No is no good as employees can have 2 positions and that would mean 2 different SAP numbers?
Any help would be appreciated.
Thanks
Your question is not really clear on what is the problem, and what you want to accomplish.
I assume you're speaking about the HCM/HR module.
An employee that belongs to several companies will possess several employeeid's. If an employee occupies two positions in the same company, it will have only one employeeid (field pernr in all infotypes tables). However, it has two relationship with "S" objects (Job) in OM.
If you have an employee in several companies, you can create a solution. There are a lot of ways to do so (as always with SAP). It depends also on what (sub) module you want to use ? PA ? OM ?
In the first case, you could use a field of the IT0032 (badge for example), or create a shared infotype, with a GroupId / UniqId that is filled during infotype creation.
In the second case, you could use the "CP" object (central Person) in OM to get a relationship with all the P objects (person / employeeId) of the employee.
It really depends on the HR Processes and the current customization of your SAP system.
SAP HCM has the transaction PA20 which display personnel data. Actually, the right name of transaction is: Display HR Master Data.
Execute PA20.
Look up the field you want.
Hit F1 over there.
Hit over hammer icon.
Look up field name and table name.
OR
to run SE16, accessing the table: PA0105 and column name: PERNR - Personnel number.

Proper way to model user groups

So I have this application that I'm drawing up and I start to think about my users. Well, My initial thought was to create a table for each group type. I've been thinking this over though and I'm not sure that this is the best way.
Example:
// Users
Users [id, name, email, age, etc]
// User Groups
Player [id, years playing, etc]
Ref [id, certified, etc]
Manufacturer Rep [id, years employed, etc]
So everyone would be making an account, but each user would have a different group. They can also be in multiple different groups. Each group has it's own list of different columns. So what is the best way to do this? Lets say I have 5 groups. Do I need 8 tables + a relational table connecting each one to the user table?
I just want to be sure that this is the best way to organize it before I build it.
Edit:
A player would have columns regarding the gear that they use to play, the teams they've played with, events they've gone to.
A ref would have info regarding the certifications they have and the events they've reffed.
Manufacturer reps would have info regarding their position within the company they rep.
A parent would have information regarding how long they've been involved with the sport, perhaps relations with the users they are parent of.
Just as an example.
Edit 2:
**Player Table
id
user id
started date
stopped date
rank
**Ref Table
id
user id
started date
stopped date
is certified
certified by
verified
**Photographer / Videographer / News Reporter Table
id
user id
started date
stopped date
worked under name
website / channel link
about
verified
**Tournament / Big Game Rep Table
id
user id
started date
stopped date
position
tourney id
verified
**Store / Field / Manufacturer Rep Table
id
user id
started date
stopped date
position
store / field / man. id
verified
This is what I planned out so far. I'm still new to this so I could be doing it completely wrong. And it's only five groups. It was more until I condensed it some.
Although I find it weird having so many entities which are different from each other, but I will ignore this and get to the question.
It depends on the group criteria you need, in the case you described where each group has its own columns and information I guess your design is a good one, especially if you need the information in a readable form in the database. If you need all groups in a single table you will have to save the group relevant information in a kind of object, either a blob, XML string or any other form, but then you will lose the ability to filter on these criteria using the database.
In a relational Database I would do it using the design you described.
The design of your tables greatly depends on the requirements of your software.
E.g. your description of users led me in a wrong direction, I was at first thinking about a "normal" user of a software. Basically name, login-information and stuff like that. This I would never split over different tables as it really makes tasks like login, session handling, ... really complicated.
Another point which surprised me, was that you want to store the equipment in columns of those user's tables. Usually the relationship between a person and his equipment is not 1 to 1 and in most cases the amount of different equipment varies. Thus you usually have a relationship between users and their equipment (1:n). Thus you would design an equipment table and there refer to the owner's user id.
But after you have an idea of which data you have in your application and which relationships exist between your data, the design of the tables and so on is rather straitforward.
The good news is, that your data model and database design will develop over time. Try to start with a basic model, covering the majority of your use cases. Then slowly add more use cases / aspects.
As long as you are in the stage of planning and early implementation phasis, it is rather easy to change your database design.