Need ideas/advices about a database structure - sql

Let's think we have 100+ hotels, and each hotel has at least more than 3 room types.
I want to hold hotel's capacity for one year in the past and one year in the future. How should i design the database for easiest use.
Example:
A hotel has 30 rooms. 10 x "Standard
room", 10 x "Duplex Room", 10 x "Delux
room" I will keep this example on
standard rooms. Today is: 13.01.2011 I
want to keep records from 13.01.2010
to 13.01.2012 What i will store in
database is available rooms. Something
like this(for standard room):
13.01.2011: 10
14.01.2011: 9 (means 1 standard room sold for this day)
15.01.2011: 8 (means 2 standard rooms sold for this day)
16.01.2011: 10 (all available for this day)
17.01.2011: 7 (means 3 standard rooms sold for this day)
18.01.2011: 10
etc...
Thanks in advance.

Let me try to summarize your question to see if I understand it properly:
You have a set of Hotels. Each Hotel
has a set of Rooms. Each Room belongs
to one of a number of possible Room
Types. The lowest level of detail
we're interested in here is a Room.
This suggests a table of Hotels, a lookup table of Room Types, and a table of Rooms: each Room will have a reference to its associated Hotel and Room Type.
For any given day, a room is either
booked (sold) or not booked (let's
leave off partial days for simplicity
at this point). For each day in the
year before and the year after the
current day, you wish to know how many
rooms of each type were available (non-booked) at
each hotel.
Now, since hotels need to be able to look at bookings individually, it's likely you would maintain a table of bookings. But these would typically be defined by a Room, a Start Date, and a number of Nights, which isn't ideal for your stated reporting purposes: it isn't broken down by day.
So you may wish to maintain a "Room Booking Log" table, which simply contains a record for each room booked on each day: this could be as simple as a datestamp column plus a Room ID.
This sort of schema would let you generate the output you're describing relatively easily via aggregate queries (displaying the sum of rooms booked per day, grouped by hotel and room type, for example). The model also seems like it would lend itself to an OLAP cube.

I did a homework question like this once. Basically you need at least 3 tables: one which holds the rooms, one which holds the reservations, and another table that links the too because its not a specific room that is reserved at a given time, its a specific type of room.

Related

SSAS MDX Calculation - Sum based off a group value

I work for a hotel company and I have set up a fact table with the granularity of a stay night for each guest, e.g. if a guest stays for 3 nights, there would be a row for each night of the stay.
What I am trying to do is create a measure for the occupancy percentage (rooms booked divided by available rooms).
I have a column in the fact table that says how many rooms the hotel has, but just summing up that value doesn't work because then it is just multiplying the number of rooms by the number of guests. So I need to sum up the total guests and then divide by the number of rooms that that particular hotel has. Does this make sense?
[Measures].[On The Books] / [Measures].[Rooms Available]
The SQL for this would this:
SELECT stay.PropertyKey, prop.RoomsAvailable, stay.StayDateKey, COUNT(stay.Confirmation) AS Confirmation,
CAST(COUNT(stay.Confirmation) AS DECIMAL(13,9)) / CAST(prop.RoomsAvailable AS DECIMAL(13,9)) AS OccupancyPercentage
FROM dbo.FactStayNight stay
INNER JOIN
(
SELECT DISTINCT PropertyKey, RoomsAvailable
FROM dbo.FactStayNight
) prop
ON stay.PropertyKey = prop.PropertyKey
GROUP BY stay.PropertyKey, stay.StayDateKey, prop.RoomsAvailable
Your fact table is good, apart from the column with total number of rooms. The fact row is at the granularity level "Room", but the total number of rooms is at granularity level "Entire Hotel".
(You can imagine a "Real estate assets" hierarchy dimension, assuming you don't have one:
Hotel
Floor
Room
)
Possible solutions:
Add a "number of rooms" available in your Date dimension, at the Day level (strictly, "Night" level). This will sum commensurably with COUNT(Guests staying on that day). You could even adjust this number to reflect e.g. rooms under repair in particular periods.
You could implement a Room dimension, with each guest's Fact_NightStayed assigned to a Room. Then make what is technically called a "headcount" table, just like your Fact_NightStayed. But this table would be a "roomcount" table: a row indicates that a room exists on a particular day (or, if you decide, that a room exists and is usable i.e. not broken/being repaired). Pre-populate this table with one row per room per date, into the future up to a date you decide (this would be an annual refresh process). Then, joining Fact_NightStayed to Fact_RoomCount, your measure would be COUNT(NightStayed)/COUNT(RoomCount).
Watch out for aggregating this measure (however you implement it) over time: the aggregation function itself from the Day leaf level up the Date hierarchy should be AVG rather than SUM.

SQL Database Design for monthly issued coupons

I'm struggling with a database schema for a problem I'm having.
Let's say I own a business that sells monthly services (cleaning) to different companies.
However, I give companies monthly saveable 'coupons' that act like a reduction (of 5 dollars) based on their amount of users.
Example:
It's april 2018
Company XYZ has to pay 1.000 dollars for their monthly cleaning services by my business.
XYZ, has 5 employees, so they will have 5 coupons for the month of april.
HOWEVER, since coupons can be saved (for a period of 2 months), company XYZ will not use the coupons of only april, but also of march (since they didn't use any that month and february coupons are already used up).
Result:
10 coupons are used on their april invoice (5 of march, 5 of april):
total amount to pay 950 dollars
My thing is that I want to automate this. With one click on the button, my system will have to check:
How many users there are
If there are any unused coupons from last 2 months (and use those first if they exist)
Apply coupons to their invoice.
I want to design this first in a database but i'm struggling:
This is my design
Company
CompanyID
Name
User
UserID
CompanyID
UserID
Now I'm struggling with the coupon design, how can I develop this so that I can automise my problem.
I will need to save coupons per company per month.
My idea is to do it like this:
Company_Month_Coupon
CompanyID
Coupon_Count
Month
I wasn't sure if i could do this in one table and i'm not so sure with the following problem:
what if my program user decides to cancel an invoice, how would my system know from which month the coupons came?
What design would be adviced in a coupon-sharing system?
Any advice to tackling this problem would greatly appreciated.
I would go with your idea and have 2 more tables: Invoices and Invoices_UsedCoupons
Invoices:
ID (Primary key)
CompanyID
Month
Status (to set a cancelled status on your invoice if you don't want to delete from the DB)
Invoices_UsedCoupons:
InvoiceId (foreign key to Invoices table)
Coupon_Count
Month (this field is for the used coupons from Company_Month_Coupon table)
The reasons for this:
We should still store the issued coupons (in your Company_Month_Coupon table) because for each month, the number of employees may change. It means that you have to keep track of the issued coupons whenever the number of employees changes.
With Invoices and Invoices_UsedCoupons table, you could easily calculate the actual used coupons & the remaining coupons.
what if my program user decides to cancel an invoice, how would my
system know from which month the coupons came?
All the information is available in Invoices and Invoices_UsedCoupons tables. If you want to reclaim coupons after cancelling the invoice, it's also easy to do.
"I will need to save coupons per company per month."
Maybe you can do the opposite. In the database does not store coupons that can be used, but only those that are actually used, for example in the table "used_coupons"
The idea is that the coupons are given up by default, so it makes no sense to store them. Only need to save the used coupons.
At checkout you need to find out how much users is in the company and how many "used coupons" is saved in the last two months.
If X coupons are returned then from the "used_coupons" table you need to delete the latest X coupons.

MS Access: How to select entries by month using query

I make a database for theatre tickets selling system. There are tables with theatres, spectacles and sessions of spectacles (one spectacle can be showed many times). In table with sessions there is a date field. I need to make a form, where user can choose a theatre and a month, and will get a report with a list of sessions in chosen theatre for chosen month. Does anyone know how to do it?
i guess you are searching for the Month Function.So when you select a month you need to perform this on the query :
WHERE Month(DateOfSession) = " & me.cboSelectMonth

Flight Schedule DB Model SQL Server

I am trying to create a DB model in SQL Server for storing Flight schedules (not real time), i have finally come up with 2 DB model but confused, which one to choose to store the schedules.
Approach:1
For each flight, store the schedules in the same column (123X56X) along with flight name, depart time, arrival time, source, destination. (123X56X) It means that particular flight is available on Sunday(1), Monday(2), Tuesday(3), Thursday(5) and Friday(6)
Approach:2
Keep the flight name, depart time, arrival time, source, destination in one table and create a new mapping table for schedules.
Table1 - wk_days
wk_day_id wk_day_short wk_day_long
1 Sun Sunday
2 Mon Monday
Table2 - flight_schedule
flight_sch_id flight_id src_city_id dest_city_id Depart_tm Arrival_tm Duration
1 1 1 2 6:00 8:00 2:00
Table3 - flight_schedule_wk_days
flight_sch_id wk_day_id
1 2
1 3
1 4
2 2
2 3
2 4
Please suggest, which one is better?
A flight schedule database is actually quite a bit more complicated in the real world than either of your examples. (More on this in a moment.)
To answer your question: In general the normalized database approach is a better idea, especially for a transactional database. The second design is normalized. Your first option is reminiscent of old COBOL flat file systems like the original SABRE system.
Using a normalized approach makes your queries much easier and more efficient. Finding out which flights fly on a Tuesday means scanning and doing an in-string analysis on every record under option 1. In option 2 your database can use an index to answer this question without having to read and analyze each record.
On a broader note, a flight is not just an origin and a destination at a particular time on some set of days of the week. Here are some things that a real-world flight schedule database needs to be able to handle:
Flights have an airline identifier
Flights have an operator airline, which can be different from the seller (i.e. "code-share")
Flights can have multiple legs (i.e. multiple sets of origins and destinations under one number)
Flights as defined by scheduling systems do have days of the week, like your model, but they also need to have a start date and end date for the date range in which the flight will operate.
Depending on what your application is intended to do, you might need to take some or all of these into account.

Best practice for keeping historical data in SQL (for SSAS Cube use)

I am working on an Hotel DB, and the booking table changes a lot since people book and cancel reservation all the time. Trying to find out the best way to convert the booking table to a fact table in SSAS. I want to be able to get the right statsics from it.
For example: if a client X booked a room on Sep 20th for Dec 20th and canceled the order on Oct 20th. If I run the cube on the month of September (run it in Nov) and I want to see how many rooms got booked in the month of Sep, the order X made should be counted in the sum.
However, if I run the cube for YTD calculation (run it in Nov), the order shouldn't be counted in the sum.
I was thinking about inserting the updates to the same fact table every night, and in addition to the booking number (unique key) and add revision column to the table. So going back to the example, let say client X booking number is 1234, the first time I enter it to the table will get revision 0, in Oct when I add the cancellation record, it will get revision 1 (of course with timestamp on the row).
Now, if I want to look on any piroed of time, I can take it by the timestamp and look at the MAX(revision).
Does it make sense? Any ideas?
NOTE: I gave the example of cancelling the order, but we want to track another statistics.
Another option I read about is partitioning the cubes, but do I partition the entire table. I want to be able to add changes every night. Will I need to partition the entire table every night? it's a huge table.
One way to handle this is to insert records in your fact table for bookings and cancellations. You don't need to look at the max(revision) - cubes are all about aggregation.
If your table looks like this:
booking number, date, rooms booked
You can enter data like this:
00001, 9/10, 1
00002, 9/12, 1
00001, 10/5, -1
Then your YTDs will always have information accurate as of whatever month you're looking at. Simply sum up the booked rooms.