SSAS- MDX Assign fact row to dimension member base on calculation - sql-server

I am looking to calculate in the calc script something, so I can allocate a row from a fact table to a dimension member.
The business scenario is the following. I have a fact table that record customer credit and debit ( customer can do a lot of little loan) and a dimension Customer.I want to classify my customer base on his history of credit and debit on a given period.Classification of customer change over time.
Example
The rule is, if a customer balance (for a given period ) is over - 50 000, the classification is "large", if he have more than a record and have done a payement in the last 3 month he is a "P&P.If he doesn't own any money and have done a payement in the last 3 month its "regular".
My question is more about direction than a specific code,which way is the best to implement this kind of rule ?
Best Regards
Vincent Diallo-Nort

I'd create a fact table with a balance auto-updated status every day:
check the rolling balance yesterday plus today's records.
when the balance = 0, then remove a record.
Plus add a flow fact table with payments only.
Add measures:
LastChild aggregation for the first fact table.
Sum aggregation for the second fact table.
When it's done, you may apply a MDX calculation:
case
when [Measure].[Balance] > 50000
then "Large"
when [Measure].[Payments] + ([Date].[Calendar].CurrentMember.Lag(1),[Measure].[Payments]) + ([Date].[Calendar].CurrentMember.Lag(2),[Measure].[Payments]) > 0
then "P&P"
else "Regular"
end
In order to give you answer in detail you have to provide more information about your data structure.

Related

Measure that indicates sales volume per product per day (Google Data Studio)

I need to implement a measure that indicates sales volume per product per day. For the example table below (each line is a record of a sale):
id,create_date,report_date,quantity
329,2019-01-02 08:19:17,2019-01-02 14:34:12,6
243,2019-01-02 09:11:42,2019-01-03 15:30:14,6
238,2019-02-02 08:19:17,2019-03-02 14:36:17,2
170,2019-04-02 02:15:17,2019-04-02 14:37:12,2
238,2019-04-02 08:43:11,2019-04-02 14:41:01,8
238,2019-04-02 08:52:52,2019-04-02 14:39:12,1
238,2019-08-02 08:10:09,2019-08-02 15:02:12,1
238,2019-10-02 08:10:17,2019-10-02 18:34:11,1
170,2020-01-02 08:24:14,2020-01-02 19:31:31,2
170,2020-01-02 08:32:16,2020-01-02 21:52:32,3
The operations to reach the result:
1. Identify total sales and total products for each day.
For 2019-01-02, two sales were carried out, totaling 12 products (6 products for each sale on the day)
2. Divide total products by total sales, resulting in the product/sale ratio for the day (if the result is 2, it indicates that each sale on average corresponds to two products).
In the example table there are 6 different dates (YYYMMDD), for each corresponding date: total products/amount of sales on the day (12/2, 2/1, 11/3, 1/1, 1/1, 5/1) .
3. Average every day's story, resulting in a single value.
(3 + 2 + 3.6 + 1 + 1 + 3)/6 = 2.26 , indicating that on average two products are sold per sale per day.
As it involves many operations, I couldn't get a solution for this problem. If anyone can help me.
note: I accept alternative suggestions to offer the measure to indicate the volume of sales per product per day.
Please check the numbers given in your steps 2 and 3:
12/2=6 not 3
5/1 must be 5/2
I still think that you want to calculate a 'day story' in step 2, see formular below.
Here are the steps for generating such a value:
create a table
add your time as dimension and make it to date not date&time
order by date ascending (optional)
create a field day story with the formula sum(quantity)/count(id)
add this field three times to your table
click on the AUT left to the fieldname and select Running calculation to 'running average`
You have to convince your users to only look at the last line of the table.

PowerPivot. Constract formula that first agregate data from one table and then use data from another table to compute result

I have two tables. One table contains two columns RepresentativeID and SalesAmount.
The second Table contains three columns RepresentativeID, BaseAmount and RateCommision.
A representative gets a commission of let say 1% all sales over 1000.
I need to compute total commission for each representative.
How can I aggregate one table first and then connect it with another?
Welcome to Stack Overflow, Iryna!
First, you need to connect your tables on RepresentativeID.
For simplicty, I will call your first table "Sales", and the second table "Rep".
Your data model then should look something like that:
Note that Rep table should be on 1 side, and Sales table on many side (1:*)
Then, in Sales table add measure:
Rep Sale = SUM(Sales[Amount])
and another measure:
Rep Commission = SUMX( Rep, ( [Rep Sale] - Rep[Base]) * Rep[Rate])
How it works:
to calculate commissions, you need to iterate by each representative. SUMX function iterates over table Rep, calculates sales for each of them, then calculates their commissions, and then sums them up.

DB Schema: Versioned price model vs invoice-related data

I am creating some db model for rental invoice generation.
The invoice consists of N booking time ranges.
Each booking belongs to a price model. A price model is a set of rules which determine a final price (base price + season price + quantity discout + ...).
That means the final price for the N bookings within an invoice can be a complex calculation, and of course I want to keep track of every aspect of the final price calculation for later review of an invoice.
The problem is, that a price model can change in the future. So upon invoice generation, there are two possibilities:
(a) Never change a price model. Just make it immutable by versioning it and refer to a concrete version from an invoice.
(b) Put all the price information, discounts and extras into the invoice. That would mean alot of data, as an invoice contains N bookings which may be partly in the range of a season price.
Basically, I would break down each booking into its days and for each day I would have N rows calculating the base price, discounts and extra fees.
Possible table model:
Invoice
id: int
InvoiceBooking # Each booking. One invoice has N bookings
id: int
invoiceId: int
(other data, e.g. guest information)
InvoiceBookingDay # Days of a booking. Each booking has N days
id: int
invoiceBookingId: id
date: date
InvoiceBookingDayPriceItem # Concrete discounts, etc. One days has many items
id: int
invoiceBookingDayId: int
price: decimal
title: string
My question is, which way should I prefer and why.
My considerations:
With solution (a), the invoice would be re-calculated using the price model information each time the data is viewed. I don't like this, as algorithms can change. It does not feel natural for the "read-only" nature of an invoice.
Also the version handling of price models is not a trivial task and the user needs to know about the version concept, which adds application complexity.
With solution (b), I generate a bunch of nested data and it adds alot of complexity to the schema.
Which way would you prefer? Am I missing something?
Thank you
There is a third option which I recommend. I call it temporal (time) versioning and the layout of the table is really quite simple. You don't describe your pricing data so I'll just show a simple example.
Table: DailyPricing
ID EffDate Price ...
A 01/01/2015 17.50 ...
B 01/01/2015 20.00 ...
C 01/01/2015 22.50 ...
B 01/01/2016 19.50 ...
C 07/01/2016 24.00 ...
This shows that all three price schedules (A, B and C just represent whatever method you use to distinguish between price levels) were given a price on Jan 1, 2015. On Jan 1, 2016, the price of plan B was reduced. In July, the price of plan C was increased.
To get the current price of a plan, the query is this:
select dp.Price
from DailyPricing dp
where dp.ID = 'A'
and dp.Effdate =(
select Max( dp2.EffDate )
from DailyPricing dp2
where dp2.ID = dp.ID
and dp2.EffDate >= :DateOfInterest);
The DateOfInterest variable would be loaded with the current date/time. This query returns the one price that is currently in effect. In this case, the price set Jan 1, 2015 as that has never changed since taking effect. If the search had been for plan B, the price set on Jan 1, 2016 would have been returned and for plan C, the price set on July 1, 2016. These are the latest prices set for each plan; that is, the current prices.
Such a query would more likely be in a join with probably the invoice table so you could perform the price calculation.
select ...
from Invoices i
join DailyPricing dp
on dp.ID = i.ID
and dp.Effdate =(
select Max( dp2.EffDate )
from DailyPricing dp2
where dp2.ID = dp.ID
and dp2.EffDate >= i.InvoiceDate )
where i.ID = 1234;
This is a little more complex than a simple query but you are asking for more complex data (or, rather, a more complex view of the data). However, this calculation is probably only executed once and the final price stored back in to the invoice data or elsewhere.
It would be calculated again only if the customer made some changes or you were going through an audit, rechecking the calculation for accuracy.
Notice something, however, that is subtle but very important. If the query above were being executed for an invoice that had just been created, the InvoiceDate would be the current date and the price returned would be the current price. If, however, the query was being run as a verification on an invoice that was two years old, the InvoiceDate would be two years ago and the price returned would be the price that was in effect two years ago.
In other words, the query to return current data and the query to return past data is the same query.
That is because current data and past data remain in the same table, differentiated only by the date the data takes effect. This, I think, is about the simplest solution to what you want to do.
How about A and B?
It's not best practice to re-calculate any component of an invoice, especially if the component was printed. An invoice and invoice details should be immutable, and you should be able to reproduce it without re-calculating.
If you ever have a problem with figuring out how you got to a certain amount, or if there is a bug in your program, you'll be glad you have the details, especially if the calculations are complex.
Also, it's a good idea to keep a history of your pricing models so you can validate how you got to a certain price. You can make this simple to your users. They don't have to see the history -- but you should record their changes in the history log.

How can I split data from a second dataset in SSRS

I have two tables in SSRS. One holds the amount of insurance claims in a given month and one holds the amount of insurance complaints in a given month
Each table is calculated by either =COUNT(Fields!Claims.Value) for claims and =COUNT(Fields!Complaints.Value) that is simple enough and is split over the current 10 months of a year
Where it gets tricky though is that the claims table has an additional line where it calculates complaints as a ratio of claims. My current expression reads as follows:
=COUNT(Fields!Complaints.Value, "Complaints"/=COUNT(Fields!Claims.Value)
but the problem I have is that it's taking the full YTD value of the complaints and dividing by the monthly amount of claims.
ASK:
How can I get a calculation similar to above but only dividing complaints by month and claims by month - but keeping in mind that the complaints data comes from a different table
You can use LookupSet function to get the claims in the same month.
Create a tablix and use the Complaints dataset in the DataSetName property.
Add Month as Row Group.
For complaints column use:
=Count(Fields!Complaints.Value)
For claims column use:
=LookupSet(Fields!Month.Value,Fields!Month.Value,Fields!Claims.Value,"Claims").Length
For Ratio column use:
=IIF(
ReportItems!Textbox69.Value=0,0,
Count(Fields!Complaints.Value)/ReportItems!Textbox69.Value
)
Replace Textbox69 by the name of the textbox where Claims (LookupSet) expression is placed.
Note the validation for zero denominator in case there is no claims in a given month.
It should produce:
Let me know if this helps.

Calculate number of full time equivalent employees using DAX measures

I am able to calculate how many employees are working using DAX measures:
Number of employees started := CALCULATE(COUNTA([Emp from]);FILTER(ALL(tDate[Date]);tDate[Date]<=MAX(tDate[Date]))) -
Number of employees quit := CALCULATE(COUNTA([Emp unitl]);FILTER(ALL(tDate[Date]);tDate[Date]<=MAX(tDate[Date])))
Number of employees working := [Number of employees started] - [Number of employees quit]
But I have not managed to calculate how many full time equivalent employees are working. Each employ has a workload from 0% to 100%.
How can I calculate the number of full time equivalent employees?
I have tried the following for number of full time equivalent employees started, but in contrast to the measures above it doesn't accumulate over time. It just shows the results for each individual month:
Number of full time equivalent employees started:=CALCULATE(SUMX(tEmployees;tEmployees[Workload]*Not(ISBLANK(tEmployees[Emp from])));FILTER(ALL(tDate[Date]);tDate[Date]<=MAX(tDate[date])))
Do you have any suggestion for how I can solve this?
You might try something like this. In your Emp table have the start date and end date for the employee. In your measure you would use the calculatetable function to create an in memory table that has one row for each date in your date table and each employee id. This same in memory table would take the work percentage and create a column that that represents the number of hours worked by that employee on that day. Then you just need to express number of 'equivalent' employees as: sum of number of hours worked/(number of hours in a 'full time work day' * count of days in period). This should give you a measure you can use along with your dates to find the number of full time equivalent employees in on any given day or over any given period.
See my sample table structure in this TechNet forum post. This is a modelling problem first, and a DAX problem second.
Once you've created your headcount fact, all of this becomes trivial.

Resources