SSAS MDX Calculation - Sum based off a group value - ssas

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.

Related

Distinctcount - suppliers for departments over a period of time - slow performance

In a model that contains the following dimensions:
- Time - granularity month - 5 years - 20 quarters - 60 months
- Suppliers- 6000 suppliers at lowest level
- departments - 500 departments on lowest level
I need to have the distinct count of the suppliers for each department.
I use the function:
with member [measures].[#suppliers] as
distinctcount(([Supplier].[Supplier].[supplier].members
,[Measures].[amount]))
)
select [Measures].[#suppliers] on 0
, order([Department].[Department].[department].members, [#suppliers], BDESC) on 1
from [cube]
where [Time].[Time].[2017 10]:[Time].[Time].[2018 01]
The time component may vary, as the dashboard user is free to choose a reporting period.
But the MDX is very slow. It takes about 38ms to calculate the measure for each row. I want to use this measure to rank the departments and to calculate a cumulative % and assign scores to these values. As you can imagine performance will not improve.
I have tried to use functions and cache the result, but results - for me - got worse (according to the log 2x as bad).
What can I do to improve the performance?
To go fast adding a measure that calculates de Distinct Count on the Supplier ID of the table associated to[Measures].[Amount] will help. In the Schema definition.
The other ones are not scalable as Supplier is growing.
Nonetheless, why did you use DistinctCount instead of Count(NonEmpty())) ?
DistinctCount is mainly for calculating the number of members/tuples that are different in a set. It only makes sense if it's possible to have two same members in a set. As our initial members have no duplicated, it's useless.
Count(NonEmpty()) filters the set whith the nonempty and counts the number of items in the set. This can be easily calculated in parallel

Powerpivot sum from dimension table

I am a graduate intern at a big company and I'm having some trouble with creating a measure in PowerPivot.
I'm quite new with PowerPivot and I need some help. I am the first person to use PowerPivot in this office so I can't ask for help here.
I have a fact table that has basically all journal entries. See next table. All entries are done with a unique ID (serialnumber) for every product
ID DATE ACCOUNT# AMOUNT
110 2010-1-1 900 $1000
There is a dimension table with has all accounts allocated to a specific country and expense or revenue.
ACCOUNT# Expense Country
900 Revenue Germany
And another dimension table to split the dates.
The third dimension table contains product information, but also contains a column with a certain expense (Expense X).
ID Expense X ProductName Productcolour
110 $50 Flower Green
I made sure I made the correct relations between the tables of course. And slicing works in general.
To calculate the margin I need to deduct this expense x from the revenue. I already made a measure that shows total Revenue, that one was easy.
Now I need a measure to show the total for Expense X, related to productID. So I can slice in a pivot table on date and product name etc.
The problem is that I can't use RELATED function because the serial number is used multiple times in the fact table (journal entries can have the same serial number)
And if I use the SUM or CALCULATE function it won't slice properly.
So how can I calculate the total for expense X so it will slice properly?
Check the function RELATEDTABLE.
If you create a dummy dataset I can play around and send you a solution.

How to calculate the number of days from two dates in a table and store it in another field of the same table in Access 2013

I am making a basic hospital management system in Access 2013.I have two tables named "Bed" and "Receipt".
Bed(BedID,AssignedDate,PatientID,DischargeDate,BedCharges)
Reciept(ReceiptID,PatientID,BedCharges)
I want to calculate "BedCharges" by calculating the number of days using "AssignedDate" and "DischargeDate" and then multiplying with a constant amount of charges per day.
Also the BedCharges calculated in "Bed" Table also needs to be in the "Receipt" table.
How can I count the number of days and then calculate the "BedCharges" in both the tables?

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.

Need ideas/advices about a database structure

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.