How to improve/maximize current Database/Table Structure efficiency? - mysql

The current structure of my Database tables are as follows; I have two tables, Users, and Skills, with the following columns:
Users
user_id f_name l_name biography password email role
_____________________________________________________________________
1 John Program Short Bio Password johnprogram# Programmer
2 Jeff Analyst Another Bio Password jeffanalyst# Finance Analyst
3 Mister Manager My Bio Password mrmanager# Project Manager
Skills
user_id skill_1 skill_1_details skill_2 skill_2_details skill_3 skill_3_details
_________________________________________________________________________________
1 PHP John writes PHP Python John writes Python Perl John writes Perl
2 Excel I use Excel daily SAP SAP Reporting Reporting Reports created with Excel
3 Billing Oversee Bill. Team Workflow Assignment I assign team acc.
Whenever I am querying the data in the tables to display on a Profile Page, the info is displayed as follows:
Name: John Program
Role: Programmer
Short Bio
Skill: PHP
Details: John writes PHP
Skill: Python
Details: John writes Python
Skill: Perl
Details: John writes Perl
Questions:
1) What re-adjustments/changes should be made to the table structures to increase efficiency/flexibility given the display requirements?
2) If I were to add a "Previous Projects Using Skill" column, for efficiency, would I add it to the second table as follows?:
user_id skill_1 skill_1_details projects_using_skill_1
_________________________________________________________________________________
1 PHP John writes PHP 8 Python John writes Python Perl John writes Perl
2 Excel I use Excel daily 12 SAP SAP Reporting Reporting Reports created with Excel
3 Billing Oversee Bill. Team 3 Workflow Assignment I assign team acc.

For the skill - user relation, you can have two different solutions: if each user has its own skills and details, than you can use a skill table to represent them, with only one skill per user per row (so if a user has four skills, the table will have four rows):
Skills (user_id, skill, detail)
with primary key the couple user_id, skill.
In this way, to find all the skills for a certain user, you can join the two table and find all the relevant information.
If instead several users can have the same skills, you should use three tables:
Users (user_id, f_name, ...)
Skills (skill_id, skill_name, skill_detail)
UsersSkills (user_id, skill_id)
or, if you want that each user has its own details about a skill, but you want to share the skills, you could do something like the following:
Users (user_id, f_name, ...)
Skills (skill_id, skill_name)
UsersSkills (user_id, skill_id, skill_detail)
For your second question, if a user has done several projects using a certain skill, assuming that you have selected the first solution above, you can define a new table:
ProjectUsers (user_id, skill, project_id)
with primary key all the three attributes, and with user_id, skill foreign key for the Skills table.

Related

Client Management DB Design - Track credit based purchases

My reservation system allows us to purchase credits for clients in terms of pre defined packages. I'm struggling with how I record and calculate available credits.
Let's say we're talking about a car wash service. A client can have multiple cars and can purchase the following services, 'Wash and Wax' and 'Detailing'.
Client 1 has two cars, Car A and Car B. He brings them both in and purchases:
Car A - 1 Wash and Wax
Car A - 1 Detailing
Car B - 10 Wash and Wax
Car B - 1 Detailing
This generates 4 rows in my Purchases table, one for each service purchased.
In my DB I have two related tables tracking purchases and reservations. Table 1 Purchases, Table 2 Reservations.
In Purchases I have the following fields of note:
id
client_id
car_id
service_id
credits_purchased
credits_scheduled
credits_used
cart_id
Then in my Reservation table I have the following fields of note:
id
client_id
car_id
service_id
reservation_date
completed_datetime
car_in_datetime
car_out_datetime
purchase_id
I track the credits available by updating the Purchases table fields credits_used and credits_on_schedule as events happen.
For example, when the client makes a reservation the system adds a new record in the Reservations table, once this happens the system also runs an update query and adds +1 to the related Purchases table credits_on_schedule. When the Reservation is updated to complete the system also updates the Purchases table and adds -1 to credits_on_schedule and +1 to credits used. Simple math between credits_purchased, credits_used, and credits_on_schedule derive what credits are available for a client to use.
I feel like this isn't a good way to track the credits. My question is what is a better implementation? Should I just track credits_purchased then use count queries on the Reservation table to calculate credits_used and credits_on_schedule? Should I be using a pivot table to track? I can't seem to wrap my head around what is the cleanest design.
It looks to me that the design is ok in general.
A reservation can only have one purchased related to it so purchase_id field is a foreign key in Reservation table.
Nevertheless, my advise to you is to create a log system of all these record updates.
As you mentioned, as events are fired the system updates the calculated fields.
What if for some reason the system fails at a certain point? You should be able to track these events.
One way to avoid this is, as you mentioned, calculate credit_used by a count query on all completed reservations.

Strange database schema - is it many-to-many?

I have a strange database schema and can't decide if it's many-to-many or something else.
I have this three tables:
Table 1: Programs (retrieved by API)
id
api_id
api_program_name
...
Table 2: Program_Conditions (also retrieved by API)
id
program_id
program_conditions_group_id
api_id
description
reward
...
Table 3: Program_Conditions_Groups
id
reward
description
Well, you normally would think that the Program_Conditions is the pivot table and Programs as well as Program_Conditions_Groups are many-to-many to each other.
The problem is that Programs can have many entries in Program_Conditions_Groups but Program_Conditions_Groups can only belong to one Program.
The purpose is that Program_Conditions_Groups groups all entries from Program_Conditions which belong to a certain program to display them grouped with the same description and reward. If I'd add the description and reward to Program_Conditions it could be the same in many entries and thus it'll be redundant.
Edit based on Helio's answer:
Program OTM Program_Conditions
Program_Conditions_Groups OTM Program_Conditions
(Program OTM Program_Conditions_Groups)
A Program can kinda have many Program_Conditions_Groups through Program_Conditions. I need to access the Groups through a Program and also a single Group through a Program_Condition.
Edit 2: As of Walter Mitty's comment:
Let's assume there's this data in the three tables:
Program
id api_program_name
1 Program One
Program_Conditions
id program_id program_conditions_group_id description reward
1 1 1 Lorem 10
2 1 1 Ipsum 10
3 1 1 Dolor 20
Program_Conditions_Groups
id description reward
1 Lorem Ipsum 10
Well, now I want to fetch all programs with all their groups. If I want to fetch a Program_Condition I also need to know which group it has.
I don't know if that design is right and if it's many-to-many even if a group can only belong to exactly one program. I don't feel comfortable with that design because I need to go through maybe 100 or even 1000 conditions, group them by group_id to get one single group.
So what do I have here? Am I even doing it right or is there a better design?
I dont think I got it properly.
You mean that:
Programs OTM Programs_Conditions OTM Program_Conditions_Groups
or
Programs OTM Programs_Conditions MTM Program_Conditions_Groups
OTM - one-to-many
MTM - many-to-many
if it's the first option, I would suggest you to use the fk in the "Program_Conditions_Groups" table, since it would be easier for you to retrieve the info.
Can you describe your scenario a little bit more?

ms access create report with two tables

I am needing to create a report between two tables. One table has ID, FirstName, LastName. The seconded table has NoteID, ID and Notes. There is a one to many relationship. Each person can have many notes. What I would like to do is fill a listbox or textbox with the notes that belong to that person.
On that note, how can I create a report that will display somewhat as the following:
First Name: Jeff Last Name: Smith
Notes:
This is note 1 for Jeff Smith
This is note 2 for Jeff Smith
This is note 3 for Jeff Smith
This is note 4 for Jeff Smith
First Name: Kim Last Name: Yung
Notes:
This is note 1 for Kim Yung
This is note 2 for Kim Yung
Thank you for any thing on this to lead me in the right direction.
Okay - so I made a query to use as the Record Source for the Report.
SELECT People.ID,
People.FirstName,
People.LastName,
Notes.NOTES
FROM People INNER JOIN Notes
ON People.ID = Notes.ID;
I clicked report design, set this query as the Record Source for the report.
I added a GROUPING on ID (this is to separate each person's Notes).
This created an ID HEADER, which is where you put FirstName, LastName, and your Notes label.
In the Detail section, you put the NOTES field from your query.
Output
If you have any other questions, let me know.
What you need is a Subreport. A Report that will have another report in it. This works in a similar way to a Main Form and Sub Form. More information is available on the MS Office website : https://support.office.com/en-ca/article/Create-and-use-subreports-816f987a-4615-4058-8f20-ce817093bb33

Database Design for Time Table Generation

I am doing a project using J2EE(servlet) for Time Table Generation of College.
There are Six Slots(6 Hours) in a Day
4 x 1 HR Lectures
1 x 2 HR Lab
There Are three batches ( 3IT, 5IT, 7IT)
2 Classroom
1 LAB
Each slot in the time table will have
(Subject,Faculty)
For Lab I will duplicate the slot.
The Tables
Subject(SubjectID INT, SubjectName VARCHAR);
Faculty(FacultyID INT,FacultyName VARCHAR,NumOfSub INT,Subjects XYZ);
Here I am not able to decide the DATATYPE for subject. What should I do ? Since a faculty can teach multiple subjects ? Also how to link with Subject Table ?
P.S. Using MySQL Database
You don't want to actually store either NumOfSub (number of subjects) OR Subjects in Faculty. Storing subjects that way is a violation of First Normal Form, and dealing with it would cause major headaches.
Instead, what you want is another table:
FacultySubject
----------------
FacultyId -- fk for Faculty.FacultyId
SubjectId -- fk for Subject.SubjectId
From this, you can easily get the count of subjects, or a set of rows listing the subjects (I believe MySQL also has functions to return a list of values, but I have no experience with those):
This query will retrieve the count of Subjects taught by a particular teacher:
SELECT Faculty.FacultyId, COUNT(*)
FROM Faculty
JOIN FacultySubject
ON FacultySubject.FacultyId = FacultyId.FacultyId
WHERE Faculty.FacultyName = 'Really Cool Professor'
GROUP BY Faculty.FacultyId
... and this query will get all the subjects (named) that they teach:
SELECT Subject.SubjectId, Subject.SubjectName
FROM Faculty
JOIN FacultySubject
ON FacultySubject.FacultyId = FacultyId.FacultyId
JOIN Subject
ON Subject.SubjectId = FacultySubject.SubjectId
WHERE Faculty.FacultyName = 'Really Cool Professor'
(note that this last returns the subjects as a set of rows ie:
SubjectId SubjectName
=========================
1 Tree Houses
2 Annoying Younger Sisters
3 Swimming Holes
4 Fishing
)

What table structure would best fit this scenario?

I am developing an evaluation system for different programs that needs a lot of flexibility. Each program will have different things to track, so I need to store what data points they want to track, and the corresponding data for the person being evaluated on the particular data point. I am guessing several tables are appropriate. Here is a general outline:
Table: accounts
- unique ID assigned to each account. We'll call this 'aid'
Table: users
- each user with unique ID.
Table: evaluation
- each program will enter in the metrics they want to track into this table (i.e attendance)
- column 'aid' will correspond to 'aid' in account table
Table: evaluation_data
- data (i.e attendance) entered into this database
- column 'aid' will correspond to 'aid' in account table
- column 'uid' will correspond to 'uid' in user table
The input form for evaluation_data will be generated from what's in the evaluation table.
This is the only logical way I can think of doing this. Some of these tables will be growing quite large over time. Is this the most optimal way of doing this?
I'm a little confused about how accounts, users and programs all relate to each other and whether or not account and program are the same thing and that you used the terms interchangeably. I'm going to use different terms which are just easier for me to understand.
Say you have a website that allows freelancers to keep track of different projects and they can create their own data to track. (Hope you see the similarity)
Tables...
freelancers
id title etc
projects
id freelancer_id title description etc
data_options
id freelancer_id title
You can even add other columns like data_type and give options like URL, email, text, date, etc which can be used for validation or to help format the input form.
example data:
1 5 Status
2 5 Budget
3 5 Customer
4 99 Job Type
5 99 Deadline
6 102 Price
7 102 Status
8 102 Due By
This display 3 different freelancers tracking data, freelancers with the id's 5, 99, and 102. Deadline and Due By are essentially the same but freelancers can call these whatever they want.
data_values
id project_id option_id option_value
a column freelancer_id as you would be able to to a join and get the freelancer_id from either the project_id or the option_id
example data:
1000 1 2 $250
1001 1 1 Completed
1002 1 3 Martha Hayes
This is only showing information freelancer with the id 5 has input because option_id's 1-3 belong to that user.