Create a table using primary key of another table, that is composed of multiple columns - mysql

In hotel booking websites, hotelier creates rate plans for each room category (Super Delux, Suit Room, etc.). And each rate plan has rates based on many things.
e.g. followings are considered as rate plans
Super Delux room (Room only) (Payment mode: pay#hotel)
Super Delux room (Room only) (Payment mode: pay now)
Super Delux room (Room + breakfast) (Payment mode: pay#hotel)
Super Delux room (Room + breakfast)(Payment mode: pay now)...
Followings are the things on which a rate plan varies
1: Date - Rates can be different for every day
2: Contract Type - Rates on application booking,website booking and travel agents are different
3: Occupancy Type - Rate for single person, 2 people and 3 people are different
4: rate_plan_rate_master is used to save these rates. We need to keep 2 years of data in this table.
.
.
.
50,000 Hotels * 40 Rate Plans * 6 Occupancy Types * 4 contract types * 730 Days = 8,760,000,000 records
Followings are the different approaches that I could think of
APPROACH 1
35,040,000,000 Records
.
.
.
rate_plan_rate_master table
date (pk)
id_rate_plan (pk/fk)
contract_type (pk/fk)
id_occupancy_type (pk/fk)
rate
.
.
.
APPROACH 2 : Dont keep occupancies in different tables
5,840,000,000‬ Records
rate_plan_rate_master table
date (pk)
id_rate_plan (pk/fk)
contract_type (pk/fk)
rate_single
rate_double
rate_triple
rate_extra_child
rate_extra_adult
rate_extra_infant
.
.
.
APPROACH 3 : Create different tables to save rates for different contract types (split table into tables)
1,168,000,000‬ Records in each table
rate_plan_rate_master_web
rate_plan_rate_master_mobile
rate_plan_rate_master_b2b
rate_plan_rate_master_travel_agent
Following things will help you understand the requirements :
Occupancy types won't change in the near future. Maybe 1 or 2 types could be added as extra_child2, extra_adult2...
Usually not all the hoteliers enter the price for all types of occupancies... Small hotels don't add prices for Triple, Squad, extra_infant, extra_child.
Should I use a composite key? Or the primary key of one column and unique constraint on other fields.
This table's PK will be passed in booking_details table
This table requires only 2 years of data, but that doesn't mean we would remove it once it gets older. We want the data for analytic purposes. So right now what I can think of is that every day we will run a service or job in laravel that will remove 2 years old data from this table and add it somewhere else. If this is a solution please help me where should I send it, another table, CSV file or something else.

Related

Better to have one master table or split into multiple tables?

I am creating a database and I am unsure of the best way to design my tables. I have a table of real estate properties and I want to store information about those properties - e.g. bedrooms, bathrooms, size... I may have additional information I want to store in the future if it seems useful - e.g. last purchase price or date built, so I need to be flexible to make additions.
Is it better to create a separate table for each "characteristic" or to have one table of all the characteristics? It seems cleaner to separate the characteristics, but easier programming-wise to have one table.
CHARACTERISTIC TABLE
id property_id characteristic value
1 1 bedrooms 3
2 1 bathrooms 2
3 1 square feet 1000
4 2 bedrooms 2
...
OR
BEDROOM TABLE
id property_id bedrooms
1 1 3
2 2 2
...
BATHROOM TABLE
id property_id bathrooms
1 1 2
...
Forgive me if this is a stupid question, my knowledge of database design is pretty basic.
I would suggest a middle ground between your two suggestions. Off the cuff I would do
property table (UID address zip other unique identifying properties)
Rooms table ( UID, propertyID, room type , room size,floor, shape, color, finish, other roo specific details ect..)
Property details (uid, propertyID, lot size, school district, how cost, tax rate, other entire property details)
Finally a table or two for histories eg.
Property sales history(UID, PropertyID , salesdate, saleprice, sale reason, ect..)
Often grouping your data by just "does it match" logic can yield you good results.... care needs only be taken to account for 1to1 and 1tomany relationship needs of tables.
I am focused to this:
"I have a table of real estate properties"
Now as far as i knew you has to be a different type of:
Houses
Bedrooms
Comfort room and so on.
For further explanation:
You has to be a table of:
1. House type
2. House names,description,housetypeid,priceid,bedroomid,roofid,comfortroomid and any other that related to your house.
3. Bedroom type
4. Comfort room type
5. Dining type
6. roof type if it has.
7. House prices
8. Bathroom type
something like that.
One table with a few columns:
Columns for price, #br, #bath, FR, DR, sqft and a small number of other commonly checked attributes. Then one JSON column with all the other info (2 dishwashers, spa, ocean view, etc).
Use WHERE clause for the separate columns, then finish the filtering in you client code, which can more easily look into the JSON.

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.

How do I structure MySQL tables where one field could contain multiple values (but might not)?

I'm designing a web app which allows users to attend events and search for specific types of events.
Say, for instance, that these events are taking place in Hogwarts. The students have their own table where their studentID is held as a primary key, and this also contains which house they are a part of (of which there are 4), the subject they take, and which year of study they are in (e.g. 1 or 4 or 5, etc). The events can be for all students, specifically for 4th year students in the Ravenclaw house, or anywhere in between.
The events are held in an events table, which contains an eventID as the primary key, but I'm not sure how to hold the data for the house/year/subject it is aimed at. Obviously if an event were only aimed at 3rd year Hufflepuffs who take Potions, or something similarly specific, I could hold it within the same table. However, what if the event is for any year of Hufflepuffs (and not any Slytherins, etc)? Or if all students from all years, houses and subjects are eligible to attend? Will I need a table which holds all the years for each event and a separate table for which houses it's for and a further separate table for the subject it's aimed at?
Any advice or links are appreciated.
I think there are two ways but you definitely need at least one more table for the associations. Either you want to be very specific, about the combinations possible or you want to do it generally, like: only third years, only hufflepuffs, then the combination of the two values will be only third year hufflepuffs.
What I am trying to say are these two options.
1) One table that holds rows with very specific details:Event ID and the explicit combinations of all possible options (Here you will have a lot of rows)
This would mean that the event can be associated with second and third year hufflepuffs, but only second year slytherins.
association_id event_id year_id house_id subject_id
1 1 second hufflepuff potions
2 1 third hufflepuff potions
3 1 second slytherin potions
2) One table per property (here the disctinction is not as clear but you only have to create one row per property etc.
The following two tables could be used to store that all hufflepuffs and all slytherins that are in second or third year might attend
association_id event_id year_id
1 1 second
2 1 third
association_id event_id house_id
1 1 hufflepuff
2 1 slytherin
Does that answer your question or at least help you to find a solution?
Mybe if you can describe the target you are aiming at more closely one can find a solution suitable for your Problem together.

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.

MySQL Optimal Field Memory Usage

The situation that I am facing is that I am trying to work the best way (in terms of memory storage usage) to represent the inventory stock held by different stores at different points in time. The setup is as follows:
Table: Stores
A table which is a list of the different stores:
Store Id (PK)
Store Name
... other details
Table: Stock
Stock Id (PK)
Stock Name
... other details
Table: Store Stock Holdings
Store Id
Stock Id
Date
Quantity
(Store Id, Stock Id and Date act as a joint primary key, with Store Id and Stock Id as foreign keys)
Alternatively I thought to store the stock holdings as a json string:
Table: Store Stock Holdings
Store Id
Date
Stock Holdings
So for example let's say store 1 has 50 lemons(code = 1), 100 oranges(code =2), and 20 mangos(=3) on the Jan 1 2011, then the three setups would represent it as:
Option 1:
Store Id, Stock Id, Date, Quantity
1 , 1, 2011-01-01, 50
1 , 2, 2011-01-01, 100
1 , 3, 2011-01-01, 20
Option 2:
Store Id, Date, Stock Holdings
1 , 1, 2011-01-01, \{1,50;2,100;3,20\}
Option 3:
Would be to reduce the replication of storing the dates in Option 1 by splitting it into two tables as follows:
Index, Store Id, Date
1, 1, 2011-01-01
Index, Stock Id, Stock Holdings
1, 1, 50
1, 2, 100
1, 3, 20
So the questions are:
What would be my speed and storage considerations for the different implementations. My thinking is Option 3 and Option 2 are likely the better choice as the date information isn't replicated.
For Option 2, is the memory storing the JSON string allocated dynamically? What I mean by this is the JSON string could be potentially quite large and as a result one would need to allow for it. Would then a new entry take up the total allocation or only the required amount of memory based on the JSON string? My understanding is that using varchar will allocate the memory dynamically. Would you suggest using varchar?
MySQL is a relational database management system, so it is designed to operate on normalized relational data.
This means that it cannot efficiently index JSON strings: you won't be able to say, search by stockId efficiently, run aggregate queries grouping by stock etc.
The only thing you'll be able to do fast is to retrieve all store contents (whether you need it or not) given the store id.
So option 2 is only viable if you are using MySQL as a pure key-value storage. There are many systems on the market which are better suited for that purpose.
As for choosing between option 1 and option 3, the latter just replaces a natural composite key (storeId, date) with a surrogate one (index).
An integer is shorter in size than INT + DATE combination, so there may be edge cases when this option is better (especially if you have few dates with really many entries on each date and you don't need to query all stores or all dates given a stock). However, keeping everything in one table lets you create composite indexes on any combination of storeId, stockId and date which may be crucial for performance.
To help you choose between the two, we need to know what kind of queries will you be running, but option 1 (with storeId, stockId and date in one table) would be definitely the model of choise.