Problem with an agenda/availability query - mysql

I have a mysql table with users and their weekly calendar.
Every user can set his own availability for the week (morning, afternoon, night / MON thru SAT), and that is not going to change often, almost never.
Imagine those users are personal trainers in a gym, or tennis courts you can book...
My problem here is to find the right query (or maybe even rethinking the way i'm storing that data in mysql) in order for an external web user to check availability of them based on 3 check buttons [o]morning, [o]afternoon, and [o]night
So I want my web user to go to my website and check/uncheck those buttons in order to see which one (personal trainer, or whatever) is available
So if I check Morning i can see only the people available, also (but not only), in the morning,(because a personal trainer can be available during the morning but also in the afternoon etc..)..
it may sounds an easy problem but i'm having hard time...
any help is appreciated
Thanks!

This isn't really an algorithm question, this is more of a DBA question. You'd most likely have a user table and an availability table.
user:
userid
...
availability:
userid
day
timeofday
When given a query such as Monday Wednesday Morning Afternoon (assuming the relationship is (Monday OR Wednesday) AND (Morning OR Afternoon)) you can do a query such as.
SELECT userid FROM availability WHERE day='wednesday' OR day is 'monday' AND timeofday='morning' OR timeofday='afternoon'

The answer to this question will be dependant on your DB structure. If your are storing the availabile times as 1, 2, 3 or any combo of such 12, 13, 123, 23 then you can simply use a
MYSQL Regular expression to limit your results based on the input checkbox criteria.
I would suggest somthing like:
SELECT trainer FROM trainer_table WHERE availaility regexp '[Limiting Criteria]'
In the above code, simply replace trainer with the name of your fields you wish to return. Then replace trainer_table with the name of your table and finally replace Limiting Criteria with your limiting text, be it 1 or 2 or 3 or any combination.
If you want more specific help, an example of your own table structure would be helpful.

Related

Table structure of active members for 4 years in sql

I am working on an achievement system and the users can unlock a badge when they have been active on the site for 4 years.
I tried to store each time a user in logged in but it's not really a good idea.
So my question is, how the table structure should be if I want to know if the user was active for 4 years?
It depends on what you mean by active, but if you mean that four years has elapsed since they first logged on, registered etc. then you just need a date field to store the account setup / logon etc. Then when they logon you can test to see if four years has past since that date and insert a badge accordingly.
You can save the last consecutive log in and the first log in. That's just two columns. Every time a user logs in, you can check if he logged in the day before. If yes, then update that column. If not then update the first log in because that's when the 4 year period will begin again. Let me know if that makes sense or if you need examples to help with understanding the thought process.
That is too generic a question to provide an full solution. By active for 4 years it sounds like you will need to track their actions. So perhaps some sort of transaction or history table that links their userid with a datetime plus actions performed.
Then you just have to define what "active" means such as having performed specific actions at least once per week, etc.
EDIT
First off I am a SQL Server developer, but have attempted to convert this to MySQL syntax for you.
~ = primay keys to ensure uniqueness & good performance
User table
~ UserID unique user id - could be an Identity, GUID or similar field
UserName unique user name
anything else you want to track such as First Name, Last Name, etc
UserAction table
~ UserID link to User table
~ ActionType number indicating what the user performed
1 = login
add in other types in the future if you ever want to track anything else
~ ActionDate datetime of the action
anything else that you may want to track such as the duration or end date (in this case that would be them logging out)
Database systems are designed to hold lots of data so you shouldn't have to worry too much about that unless space is a factor. You can always delete any data that is older than 4 or 5 years if you like.
Normally I would just use a CTE (common table expression) but apparently they won't be available until MySQL 8.0 [https://www.mysql.com/why-mysql/presentations/mysql-80-common-table-expressions/]
So instead here is another method. It assumes that you want a login within each given year. i.e. at least one login from 2017, one from 2016, 2015 & 2014. If instead you wanted at least one login going back 1 year from today and so on then we will need to modify this query.
-- this will return the number of years with at least one login, going as far back as 4 years
SELECT COUNT(1) AS NumberOfYearsWithLogin
FROM (
SELECT YEAR(CURDATE()) - YEAR(ActionDate) AS NumberOfYearsAgo
FROM UserAction
WHERE UserID = 123 -- put user of interest here
AND ActionType = 1 -- login
AND YEAR(CURDATE()) - YEAR(ActionDate) < 4 -- check the last 4 years
GROUP BY YEAR(CURDATE()) - YEAR(ActionDate) -- group by year number with today's year as number 0
) A
;

time slot database design

I am creating a database which need to allow booking a resource from start time to end time on a particular day. For example, I have 11 badminton courts. These courts can be booked for 1 hour and it can very also and in a day each court takes 18 bookings from morning 6 am till night 12 pm. (considering each booking is for one hour). The price of booking also varies from day to day, for example morning charges are more than day charges. Weekend charges are more than weekdays charges.
Now my question is, is it advisable to pre-populate slots and then book it for user depending on the availability. But in this case for the abobe example If I need to store slots for next 1 month then I will have to store 11*18*30 = 5940 records in advance without any real bookings.Every midnight I will need to run script to create slots. If no of clubs increases this number can become huge. Is this good design for such systems? If not then what is the better designs in these scenerios.
club name||court || date || start_time || end_time || status || charge ||
a c1 20/04/2015 6:00 7:00 available
a c1 20/04/2015 7:00 8:00 available
.
.
.
a c1 20/04/2015 11:00 24:00 available
.
.
a c11 20/04/2015 11:00 24:00 available
Now my question is, is it advisable to pre-populate slots and then book it for user depending on the availability. But in this case for the abobe example If I need to store slots for next 1 month then I will have to store 11x18x30 = 5940 records in advance without any real bookings.Every midnight I will need to run script to create slots. If no of clubs increases this number can become huge.
Yes. that is a horrible method. For the reasons you have stated, plus many more.
The storage of non-facts is absurd
The storage of masses of non-facts cannot be justified
If the need to write simple code is an issue, deal with that squarely, and elevate your coding skills, such that it isn't an issue (instead of downgrading the database to a primitive filing system, in order to meet your coding skills).
Notice that what you are suggesting is a calendar for each court (which is not unreasonable as a visualisation, or as a result set), in which most of the slots will be empty (available).
Is this good design for such systems?
No, it is horrible.
It is not a design. It is an implementation without a design.
If not then what is the better designs in these scenerios.
We use databases. And given its unequalled position, and your platform, specifically Relational Database.
We store only those Facts that you need, about the real world that you need to engage with. We need to get away from visualising the thing we need for the job we have to do (thousands of calendars, partially empty) and think of the data, as data, and only as data. Including all the rules and constraints.
Following that, the determination of Facts, or the absence of a Fact, is dead easy. I can give you the Relational Database that you will need, but you have to be able to write SQL code, in order to use the database effectively.
Data Model
Try this:
Resource Reservation Data Model
That is an IDEF1X data model. IDEF1X is the Standard for modelling Relational Databases. Please be advised that every little tick; notch; and mark; the crows foot; the solid vs dashed lines; the square vs round corners; means something very specific and important. Refer to the IDEF1X Notation. If you do not understand the Notation, you will not be able to understand or work the model.
I have included:
Storage of Facts (Reservations) only. The non-fact or absence of a Fact (Availability) is easy enough to determine.
club_resource_slot.duration in the Key to allow any duration, rather than assuming one hour, which may change. It is required in any case, because it delimits the time slot.
resource_code, rather than court number. This allows any club resource (as well as a court number) to be reserved, rather than only a badminton or squash court. You may have meeting rooms in the future.
Joel's reply re the rate table is quite correct in terms of answering that specific question. I have given a simpler form in the context of the rest of the model (less Normalised, easier to code).
If you would like the Predicates, please ask.
Code/General
You seem to have problems with some aspects of coding, which I will address first:
But the problem in this approach is if I need to find the availability of court based on game,location, date and time slot then I will have to load this rate table for all the clubs and the look into actual booking table if someone has already booked the slots. Is nt the better approach be if I keep the slots in advance and then someone book , jst change the status to booked. so That query will be performed entirely in DB without doing any computation in memory.
The existence of the rate table, or not, does not create an issue. That can be accomplished via a join. The steps described are not necessary.
Note that you do not need to "load this whole table" as a matter of course, but you may have to load one table or other in order to populate your drop-downs, etc.
When someone books a court, simply INSERT reservation VALUES ()
When someone cancels a reservation, simply DELETE reservation VALUES ()
Code/Data Model
Printing your matrix of Reserved slots should be obvious, it is simple.
Printing your matrix of Available or Available plus Reserved (your calendar visual) requires Projection. If you do not understand this technique, please read this Answer. Once you understand that, the code is as simple as [1].
You need to be able to code Subqueries and Derived tables.
Determination of whether a slot is Reserved or Available requires a simple query. I will supply some example code to assist you. "Game" isn't specified, and I will assume location means club.
IF (
SELECT COUNT(*) -- resources/courts reserved
FROM reservation
WHERE club_code = $club_code
AND date_time = $date_time
) = 0
THEN PRINT "All courts available"
ELSE IF (
SELECT COUNT(*) -- resources/courts that exist
FROM club_resource_slot
WHERE club_code = $club_code
AND date_time = $date_time
) = (
SELECT COUNT(*) -- resources/courts reserved
FROM reservation
WHERE club_code = $club_code
AND date_time = $date_time
)
THEN PRINT "All courts reserved"
ELSE PRINT "Some courts available"
Please feel free to comment or ask questions.
Assuming that each booking is for one hour (that is, if someone wants two hours on the court, they're taking two bookings of one hour each) it seems to me the most efficient storage mechanism would be a table Booking with columns Court, Date, and Hour (and additional columns for the person who booked, payment stated, etc..) You would insert one record each time a court was booked for an hour.
This table would be sparsely populated, in that there would only be records for the booked hourly units, not for the available ones. No data would be pre-generated; you would only create records when a booking occurred.
To produce an daily or weekly calendar your application would retrieve the booked hours from the database and join this with its knowledge of your hours (6am to midnight) to produce a visualization of court availability.
It is probably much more efficient from a data maintenance perspective to have a table with courts (1 record per court) and a table with bookings (1 record per booking).
The BOOKING record should have a foreign key to the COURT a booking start date/time and a booking end date/time. It would also have information about who made the booking, which could be a foreign key to a CUSTOMER table or it might be a fill-in name, etc., depending on how your business works.

Access DB one ID, multiple classes and associated dates

I'm creating a DB for my office. We have about 200 employees. Each employee was required to complete at least 1 of 12 courses within 2 years of being hired (so different completion/qualification dates for every course, some people have been here 20 years, some just 1 year) to become qualified. Some have completed multiple courses. Each course has to be refreshed periodically (each refresh period is different and based on the last refresher date). I'm having trouble with the layout of the table. Here's what I have as an idea, but i'm trying to see if there is a less busy way to lay out the data. I want to be able to run a query that tells me what person has completed what class (so it would have to look at all 3 class columns). I also want to be able to tell when their qualification has lapsed, or is coming up. So far I've created an employee data table that looks like the table below.
ID Name Class1 Class2 Class3 QualDt-Cl1 QualDt-Cl2 QualDt-Cl3 LstRequal1 ...
1 Bob Art Spanish 3/17/1989 9/12/2010 3/8/2012
2 Sally Math 8/31/2012
3 George Physics History 2/6/2005 7/6/1996
4 Casey History 6/8/2000
5 Joe English Sports Physics 12/10/1993 10/15/2001 4/22/2006
The classes are listed in their own table and each class column pulls from that. The qual date refresher will be a calculated column in the query based on the last refresher date.
Is there a way to put all the classes one person is qualified for in one column and have the associated date for requalifiing for each particular cours in another column?
I think it would be less confusing if you had a table per subject and register the people's names under each one with the date passed.
Also it would probably help to declutter the table from uneccssary info like the exact date the exam was passed, you can do month and year or maybe just year? if the lee way is 2 years that would probably make more sense - also making the qulified calculation easier.
The query would work if you searched per subject maybe ? or who would qualify to do what subject this current year and then the next.
this is not much of a question that you would ask on here by the way - but hope the answer helps.
When designing a database, any time you find yourself adding columns with names like Class1, Class2, Class3 you should immediately stop and think about whether it makes more sense to put those columns in a separate child table called Classes with a link (relation) to the parent. There are several reasons for this, including:
What happens when somebody takes a fourth course? Saying "that will never happen" ignores the fact that "never is a very long time" and none of us can predict the future.
When checking whether or not someone has taken a course you really need to check (Class1 IS NULL) OR (Class2 IS NULL) OR (Class3 IS NULL) and that can get really tedious, It also means that if you do have to add Class4 then all of that SQL code has to be corrected.
Similarly, if you want to find someone who took "CPR" you'd have to look for people with (Class1 = 'CPR') OR (Class2 = 'CPR') OR (Class3 = 'CPR'). Yuck.
So, save yourself some trouble (a lot of trouble, really) and create a Classes table:
ID
ClassName
QualDate
(etc. )
...where ID is the ID number from the main table (what is called a "foreign key"). From your sample data, your Classes table would look something like this:
ID ClassName QualDate
1 Art 3/17/1989
1 Spanish 9/12/2010
2 Math 8/31/2012
3 Physics 2/6/2005
3 History 7/6/1996
...

Need help with a database design for Top 10

I am trying to come up with a database design to hold the "Top 10" results for some calculations that are being done. Basically, when all is said in done, there will be 3 "Top 10" categories, which I am fine with all being separate tables, however I need to be able to go back and later pull historical data about what was in the Top 10 at certain times, hence the need for a database, although a flat-file would work, this has the potential to hold years worth of data.
Now, it's been awhile since I have done anything serious with a database, other than something that had a couple of simple tables, so I am having some issues thinking through this design. If someone could help me with the design of it, I know enough MySQL to get the rest done.
So, in essence, I need to store: A group of 10 names, a % of the total points each name had, the rank they held in the Top 10 and a time associated with that Top 10 (So I can later query for that time)
I would think I need a table for for the Top 10 with 11 columns, one for the ID and 10 for the Foreign Key of the 'Names' table, that holds every name ever used with a PK, Name, %, and Rank. This seems clunky to me, anyone else have a suggestion?
edit:The 'Top 10' is associated with a specific set of data for 5-minute intervals, and each interval is completely independent from the previous or future intervals.
I don't recommend your solution, because then if you want to ask the database "How often has Joe been in the top 10," you have to write 10 queries of the form
SELECT Date FROM Top10 WHERE FirstPlace = 'joe'
SELECT Date FROM Top10 WHERE SecondPlace = 'joe'
...
Instead, how about a Rankings table, with fields:
id
Date
Person
Rank
Then if you want the Top 10 list for a certain date, the query is
SELECT * FROM Rankings WHERE Date = ...
and if you want to know someone's historical ranking, the query is
SELECT * FROM Rankings WHERE Person = ...
and if you want to know all the historical leaders, the query is
SELECT * FROM Rankings WHERE Rank = 1
The downside to this is that you might accidentally make two different people 8th place, and your database would allow the anomaly. But I have good news for you -- people might actually tie for 8th place, so you might actually want that to be possible!
I assume that your "Top 10" is a snapshot data in certain time. And your business logic is that "every 5 minutes" so that the time is the parent entity for table design
top_10_history
th_id - the primary key
th_time - the time point when taking the snapshot data of "Top 10"
top_10_detail
td_th_id - the FK to top_10_history
td_name_id - the FK to name
td_percentage - the "%"
td_rank - the rank
If the sequence of "Top 10" could be calculated from columns in "top_10_detail", you don't need a column to keep the sequence of it. Otherwise, you need a column to persist the sequence for it.
If you need more complicated query such as "The top 10 at 12:00 AM in last 30 days", using individual columns for "day", "hour", and "minute" would be a better idea for performance(with suitable indexes).

Hotel Reservation system Database schema

I am about to develop a online hotel reservation system...using php and mysql... I have some doubts about my current database schema and the business logic to get the hotels in which rooms are free between two particular dates...
Does anyone know of some kind of tutorial where i can get some idea about the hotel reservation schema and the business logics that should be used in the system...?
Thanks for your suggestions....
Edit :
I've figured out most of the logic... The points i am not clear about are the following...
If a user selects more than one room in a particular hotel between two particular dates how can i represent in the following reservation table...?
Table : Reservation
Field 1 : reservation_id
Field 2 : room_id
Field 3 : no. of Rooms
Field 4 : check-in date
Field 5 : check-out date
Field 6 : Customer id
How can i check what rooms are available between two dates based on the reservation table and the following rooms table...?
Table : Room
Field 1 : hotel_id
Field 2 : room_id
Field 3 : total_num_rooms
Note : The db contains more than one hotel... So it's like a user can select a city and look for rooms available in hotels in that area between two particular dates...
Also say if there are 10 numbers of room of a particular type in a hotel, i need to show only the number of rooms that are free in that particular time period.....
As a general thought, apply divide and conquer. Always.
For example, why do you think a specific customer should be able to have 'number of rooms' for a certain time span associated? What if, for example, I'm on a business trip and have my family follow me a few days later. Now, for the given time span the number of rooms is no longer a constant.
That doesn't really matter? True, you could just add another entry for the same customer. But then again, you could have done that in the first place and simplify your logic saying that a customer can only have one room at a time in a single row, but there can be rows that create overlaps in time spans for a given customer.
Also, make sure you separate Reservation and a ReservationRequest. The latter is comprised of a set of Reservations I think - because I want that room for me and my family and both criteria must be matched.
Just a few ideas. Note that this is the ivory tower approach and it can lead to massively overblown solutions. In the RealWorld (TM), stick to Marcs suggestions: Analyze the actual customers need. If handling 1% of the requests increases development time by 200%, he's not gonna like (or need) it, and vice versa.
There isn't a perfect way of representing something like an hotel reservation system.
Try talking to your client or people working in hotels to understand what they are doing now and base your system on this.
I'd guess:
A Room has a RoomType
A Customer can Book 1..n Room(s)
A RoomType has a name and a price
... and so on.
If you just use a tutorial, you might end up creating a system that doesn't fit the requirements of possible users. So talk to these future end users, figure out the business logic and start coding :)