Best way to track membership history - mysql

I am creating a membership management database. One of the aspects I want to keep track of is the duration of a membership, and I want to keep track of any breaks in membership also.
Example:
A person joins , they renew each year on time for 3 years, but then there is a lapse in renewal for 2 months on the 4th year, and then they renew. I would like to be able to see the membership period of 3 years, the 2 month lapse, and then the new renewal.
Currently (see image), I originally was planning on just updating the membership_expire field to be a year from the date of the latest renewal but then realized I would be losing the previous membership renewal history by updating that field.... So how do I work around that?
I have a feeling the solution may be to create a seperate table to keep track of each renewal but I am not sure that is the best way to do it.

The database should reflect the reality.
If a "membership" can have multiple renewals, with different periods,
then your data structure should support it.
meaning- you need to create another table with FK to membership,
and each row would represent a period of time (start and expires)

Related

How to create a database that shows a vacant doctor appointment time slots?

Context:
I am working on a tele-health application that allows clients to choose an appointment type and then choose an available time slot to take that appointment. The client can only choose the appointment type and have no access to data regarding the available doctors
Procedure:
Client chooses appointment type
A Calendar is populated with available appointments for the next 30 days (sample calandar)
Once the client selects an appointment, one of the available doctors that can provide the service are assigned to them
Variables:
Each doctor has availability slots within weekdays (might have more than one on the same day)
One doctor may give more than appointment type
each service has a duration (some appointment types are set to 30 minutes and some maybe up to 60 minutes)
Problem:
Right now I am having trouble with:
listing the available time as shown in the sample calendar above in an efficient manner. Efficiency is key as this data will be needed to be retrieved a lot. I tried creating a view that has all the possible appointments, but that solution is extremely redundant.
Accounting for appointments of different duration
Current Database Design
Ideally I would like to return a list of JSON objects that contain the available start times per day (for the next 30 days) and a list of doctor id's that can handle this appointment.
Assuming that the time slots are all the same length, then you can create a calendar of all the time slots that are available.
I would suggest that each "slot" (appointment) have the information in your appointment table -- but with the caveat that "empty" appointments would also be included. Or, have the slots as a separate table with an appointment_id when the slot is taken.
Presumably, there is some limit on when future appointments can be made -- say 3 months in the future or one year in the future. Have a weekly job that adds another week in the future to the table.
Then you can summarize and readily see both available slots and unavailable appointments.

Exclude Holidays without using a date dimension

I'm writing queries on a pre-existing mysql database. Some of those queries require me to calculate the interval between two dates without considering holidays. The problem is that my original solution (creating a date table with 40 or plus years and the flag Holiday is not feasible (as they don't let me to create another table on their database), plus I have to consider local holidays too (patrons here in Italy are holiday restricted to single towns) so with the date dimension solution i'd have to add a "Patron in" field with the name of the patron's towns each day (7000+ towns in Italy), as an added difficulty some Patrons are "floating" as "first sunday of July".
Can you think of alternate ways to achieve the objective?

Money expiration tracking

I am working with money expiration tracking problem at the moment (originally it is not money, but I have used it as a more convenient example).
An user can earn money from a platform for some mysterious reason and spent them for buying stuff (products, gifts etc.).
I am looking an algorithm (SQL query best case) to find a current balance of an user balance.
The events of spending and earning money are stored different database (MySQL) tables (let's say user_earned and user_spent). So in normal case, I would simply count user totals from user_earned and subtract spent money (total of user_spent).
BUT! There is a condition, that earned user money expires in 2 years if they are not used.
That means, if user have not used his money or used just a part of it, they will expire. If an user uses his money, they are used from the oldest not expired money record, so the balance (bonus) could be calculated in user's favor.
These are 5 scenarios with events in time, to have a better understanding on the case:
Both tables (user_earned and user_spent) have timestamps for date tracking.
I did something similar in one of my projects.
Looks like you need an additional table spends_covering with columns
spend_id, earhed_id, sum
So for each spends record you need to insert one or many rows into the spends_covering to mark 'used' money.
Then balance would be just sum of not used where date is less than 2 years.
select sum(sub.earned_sum-sub.spent_sum) as balance
from
(select e.sum as earned_sum, sum(sc.sum) as spent_sum
from earned e
left join spends_covering sc on e.earhed_id=sc.earhed_id
where e.date BETWEEN ...
group by e.earhed_id
having earned_sum > spent_sum) sub
It may be worth it to have two tables -- one (or more) with all the historical details, one with just the current balances for each 'user'. Be sure to use transactions to keep the two in sync.

Decoupling MySQL data versus ease of use

Assume a simple database for hotel reservations with three tables.
Table 1: Reservations
This table contains a check-in and check-out date as well as a reference to one or more rooms and a coupon if applicable.
Table 2: Rooms
This table holds the data of all the hotel rooms with prices per night and number of beds.
Table 3: Coupons
This table holds the data of all the coupons.
Option #1:
If you want to get an overview of the reservations for a particular month with the total cost of each reservation, you'd have to fetch the reservations, the rooms for each reservation, and the coupon (if one is present).
With this data, you can then calculate the total amount for the reservation.
Option #2:
However, there is also another option, which is to store the total cost and discount in the reservation table so that it is much easier to fetch these calculations. The downside is that your data becomes much more dependent and much less flexible to work with. What I mean is that you have to manually update the total cost and discount of the reservation table every time you change a room or a coupon that is linked to a reservation.
What is generally recommended in terms of performance (option #2) version data independence (option #1).
UPDATE:
It is a MySQL database with over 500 000 rows (reservations) at this point, but is growing rapidly. I want to optimize database performance at an early stage to make sure that the UX remains fast and responsive.
Let me start to answer this with a story. (Somewhat simplified.)
2011-01-01 I reserve a room for two nights, 2011-03-01 and 2011-03-02. You don't tell me which room I'll get. (Because you don't know yet which room I'll get.) You tell me it will cost $40 per night. I have no coupons. You enter my reservation into your computer, even though you're already fully reserved for both those nights. In fact, you already have one person on the waiting list for both those nights. (Overbooking is a normal thing, not an abnormal thing.)
2011-01-15 You raise the rates for every room by $5.
2011-02-01 I call again to make sure you still have my reservation. You confirm that I have a reservation for two nights, 2011-03-01 and 2011-03-02, at $40. (Not $45, your current rate. That wasn't our deal. Our deal was $40 a night.)
2011-02-12 One person calls and cancels their reservation for 2011-03-01 and 2011-03-02. You still don't yet have a room you know for certain that I'll be able to check in to. The other person from the waiting list now has a room; I'm still on the waiting list.
2011-02-15 One person calls and cancels their reservation for 2011-03-01 and 2011-03-02. Now I have a room.
2011-03-01 I check in with a coupon.
You can store the "current" or "default" price with each room, or with each class of
rooms, but you need to store the price we agreed to with my
reservation.
Reservations don't reserve rooms; they reserve potential rooms. You
don't know who will leave early, who will leave late, who will
cancel, and so on. (Based on my experience, once in a while a room will
be sealed with crime scene tape. You don't know how long that will last, either.)
You can have more reservations than room-nights.
Coupons can presumably appear at any time before check out.
If you want to get an overview of the reservations for a particular
month with the total cost of each reservation, you'd have to fetch the
reservations, the rooms for each reservation, and the coupon (if one
is present).
I don't think so. The price you agreed to should be in the reservation itself. Specific rooms can't resonably be assigned until the last minute. If there's one coupon per reservation, that might need to be stored with the reservation, too.
The only reporting problem is in making sure your reports clearly report how much expected revenue should be ignored due to overbooking.
The response of your answer depends of the size of your database. For small database option #1 is better, but for huge database option #2 is better. So if you could say how many rows you got in table, and the database used (oracle, sqlserver etc.) you will have a more precise answer.
You can add a table holds the data of the rooms`s historical prices and reason for change.
Table 2 only records the latest price.

Storing user data as text or ID based using lookups?

Is there any benefit to storing Days of weeks, Months, Week number, user age, etc as Lookups vs plain text entry into the database? I am creating a social website with some analytic and planning to use a Question table, Answer table and Question_Answer table to store all the data like Gender, Birth months, Age, etc so I can give each an ID to use throughout the system but some older projects I worked on people always stored these are normal text entry only. So I am seeing which design is better to go with to store all the system and user fixed list data which may or may not be used later for reporting using various metrics. If using lookus then how deep to go, do i need to create days of weeks, days of year, weeks of month, etc if I want to create a report like: Comparing number of photos shared on the first of every month for a given set of users vs last day or every month for the same users?
Given that you are using MySQL, I suggest populating a date helper table, as suggested in the top-rated answer to this question: How to fill date gaps in MySQL?
The question itself should explain why you would want this table.