Calculate Event Durations to only part within Sliced Period - powerbi

We are investigating PowerBI for a reporting solution and it does a lot of what we need. However we need to be able to do adhoc reporting on events. Each event has a start date and an end date and total seconds and do percentage calculations etc. This works really well.
However our common requirement is to specify a start date and end date of which we wish to consider data. Many of the events will span over start and end of required period or even start before the start of period and go beyond the end. What we need to do is only consider the part of events that falls within the period.
Is it possible to use a slicer to define a start/end period and then only include the number of seconds within the period sliced for each event?
This would allow us to calculate the total time for all events that fell within the period.
Update
My table consists of hundreds of thousands of rows like
EventID|VehicleID|StatusID|ReasonCodeID|StartDateTime|EndDateTime|TotalDuration
We need to look at portions of each event that fall within a selected period (start/end). However events can span periods. If part of an event is outwith a period we want to ignore that part of the duration. If whole event is outside selected period then we would ignore all of it.
For example say an event starts on 1st Feb and goes to 1st July. If the selected date range of slicer was 1st Jan to 1st March then I want to only include the time between 1st Feb and 1st Mar in Total Duration calculation

What you're asking for is doable, but how well it works would very much depend on the amount of data in your table.
You can use a DAX measure to calculate the sum of the duration for any events that fall on a given date. You can do this using a disconnected date table that you slice on (the October 2016 Power BI Desktop release includes a built-in data slicer that allows you to easily pick a range). More information on that here: https://powerbi.microsoft.com/en-us/blog/power-bi-desktop-october-feature-summary/#reportView.
You would then have a CALCULATE measure that SUMS the duration, with FILTER to ensure the event in question lands within the date range selected by the slicer. There's more specifics on this part of the question here: Optimizing Dax & model for "where date between" type queries
However, you're going one step further, in that you don't want to SUM the full duration of events that fall within a given date range - you only want to sum the duration that falls within the given date range.
In order to do that, you have to calculate the duration for each individual row at run time based on the selected date range. You can do this with a measure that uses SUMX (see below), but over a large number of records (thousands, millions) the calculation will start slowing down.
For example, if you have a disconnected date table called Date, and your event table is called Event, you can have a measure such as:
Filtered Duration =
CALCULATE (
SUMX (
Event,
DATEDIFF (
MAX ( MIN ( 'Date'[Date] ), Event[StartDateTime] ),
MIN ( MAX ( 'Date'[Date] ), Event[EndDateTime] ),
SECOND
)
),
FILTER (
'Event',
'Event'[StartDateTime] <= MAX ( 'Date'[Date] )
&& 'Event'[EndDateTime] >= MIN ( 'Date'[Date] )
)
)
MIN('Date'[Date]) in this case formula corresponds to the earliest date in the disconnected date table that is within the selected date range. MAX('Date'[Date]) corresponds to the latest date.
The last part (the FILTER) is saying "only look at events that land on a date within the range selected". The SUMX is saying "for each row, do a DATEDIFF". The MAX within the DATEDIFF is saying "choose the later of either the first date from the slicer, or the start date of the event". The reason for this is that if you select the 15th through the 20th on your date slicer, and an event starts on the 18th, you want to count from the 18th. But if the event started on the 11th, you'd want to count from the 15th. The MIN is doing the opposite with the end date.
If an event falls within the time range entirely, then it will calculate the seconds from start to end. If the end of the event is after the selected time range (for example), then it will count the seconds from the exact start of the event to midnight of the selected end date.
Note that because I've used a date table you wouldn't be able to pick partial days as a date range. You could extend this to include a time table but it gets more complicated (you'd need a separate start & end time table and then account for that logic in the above, already quite complex, formula)

Is it possible to use a slicer to define a start/end period and then
only include the number of seconds within the period sliced for each
event?
Yes, It is possible. In the Power BI Gallery there is a custom visualization that lets you filter date ranges.
You just have to drag and drop the date column in your model to the Timeline slicer in order to filter your measures.
To install it go to Gallery and search timeline in the search box, download it and import it to Power BI.
If you get stuck with the DAX expressions, include SQL code and a sample model to your question.
Let me know if this helps.

Related

Average of measures to re-calculate if a filter is applied - Power BI

I have the following calculated measure:
I also have a series of drop-down filters, such as the name of the agent, report date on the page, etc.. I need to calculate the average of the measure which will be re-calculated if any filter is applied, e.g. a date period is selected or a name of the agent is picked, etc. I tried with
=averagex(values(date,date.[Month]), [% of requests (urgent and not-urgent]).
It doesn't work if the incomplete date range is selected, e.g. from the 5th of Jan till now or when the agent filter is applied. What am I doing wrong?
Using the AVERAGEX function, it calculates the average of the criteria that will be recalculated in any filtering process that I create from the data I have.
At the same time, the data centered on the date that can be set in the slicer is being calculated.
enter image description here

Power BI: Change filter context for the map visual

I need your suggestions regarding the map visual. I have a table with a list of events. Each event has a corresponding latitude, longitude, start date, and end date. The date table has an active relationship with the start date column.
My customer's requirement is to be able to use a date slicer to select any date period, and have the map to show all the active events as per that date. When the selected date period intersects with the period between the event start date and end date, such an event should be shown on the map.
Although I can change filter context and calculate all the necessary metrics related to active events as of any arbitrary date period, I am not able to make the map show me all the active events. It only shows the events with their start date falling within the selected date period.
I tried to put the active event indicator to the map filter area (Active Events is greater than 0), but it doesn't help.
Thanks in advance for your suggestions.
You need to add a new table "Active Dates", and add a measure that filters your events as
CALCULATE(COUNTROWS('Event') //Or whatever
FILTER('Event',
NOT(ISEMPTY(
FILTER('Active Dates',
'Event'[StartDate]<='Active Dates'[Date]
&& 'Event'[EndDate]>='Active Dates'[Date]
)))))
You could also include extra logic to allow (Blank) [StartDate] and/or [EndDate], and something to exclude dates that are in the future (if these are appropriate).
If this is not efficient enough, you can change it to use MIN('Active Dates'[Date]) and MAX('Active Dates'[Date]), rather than filtering 'Active Dates', at the cost of making your report only work if a contiguous range of dates is selected.

Can a measure be created in Power BI that references two tables that share no relationship?

I'm trying to create a matrix table in Power BI to display the monthly rent projections for a number of properties. I thought I could simply create a measure that summed the rent from one table and then displayed it by month based on start and end date conditions, but it's been a while since I created any measures and I had forgotten that there needs to be a relationship between columns, among other things.
Data Model
A site can have more than one lease associated with it and a lease can have both car-parks and floors associated with it, of which there can be multiple.
In addition to the tables in the linked image, once I had sorted out what I thought would be the easy step I was going to add another table which includes the estimated percentage rent increase and the period in which the increase will occur.
I started out by trying to create a measure along the lines of the following:
Matrix Test =
IF (
HASONEVALUE ( Period[Month] ),
IF (
Period[Month] >= Leases[Custom Start Date],
SUM ( Floor_Rent[Annual Rent] ) / 12,
0
),
0
)
This would need to be expanded upon because the end date of a lease would also need to be taken into consideration.
As well as forgetting about the relationship requirements, I've forgotten how to deal with the issue of narrowing down to a single value within a column.
The result is supposed to be something that looks like this:
The blanks indicate a lease that starts in the future or ends within the time-frame displayed.
When I try linking the Leases table and the Period table on Leases[Start month for current term] and Period[Month] all I can get to is a table that shows the rent amount in the month the lease starts.
Is what I'm trying to achieve possible? If so, how do I accomplish the desired result?
Link to .pbix file
Solution
The direct answer to the title question is probably 'no', but while trying to figure out how I could use Pratik Bhavsar's LOOKUPVALUE suggestion I had a thought and performed a clumsy google search - power bi create table for each value in column - and found this post. By meddling with some of the DAX in said post I was able to come up with the following:
Test Table =
GENERATE(
SELECTCOLUMNS(
VALUES(Leases[Lease ID]),"Lease ID",[Lease ID]
),
SELECTCOLUMNS(
VALUES(Period[Month]),"Month",[Month]
)
)
The result is a table with each Lease ID mapped against each Month. I can't claim to understand exactly how the functions work, and it's not the outcome I thought I needed, but it allows me to achieve exactly what I set out to do.
I've accepted Pratik Bhavsar's answer because it effectively accomplishes the same thing as the work around I implemented. Pratik's solution might be better than what I eventually landed on, but I need to have a closer look at how the two compare.
The following DAX will give you a table with all buildings mapped against all rows in the period table, eliminating the requirement of a relationship.
SiteToPeriod =
CROSSJOIN(
SELECTCOLUMNS(Sites1, "Building name/label", Sites1[Building name/label]),
Period
)

Calculate rates from previous month based on current month in order to make then visually comparable

Maybe this is an easy one but since I’m very new in DAX and PowerBI I can’t figure it out. My database has daily data ranging from MAY/17 to JUN/17 (and it’ll still going in the future). It has information of DATE, DAY, YRMTH (year-month), QT_APRV (approved customers) and QT_TOTAL (total consumers). Sample below (using Excel just to be quicker):
I wanted to create in PowerBI a bar chart with QT_TOTAL per day and a line chart with approved rate of consumer. For the rate, I used:
APPRV_RT = SUM(database[QT_APRV]/SUM(database[QT_TOTAL])
And then, selecting only a month by time in the chart (just like I want), I have:
Perfect, but now I want to create a new line chart, showing the approved rate in each respective day of the last month. Using my example, when june data are select, the first line chart has to show the daily approved rate of june AND the other the approved rate of may, in order to make it comparable (june1 -> may1; june12 -> may12 and so on). Here’s what I want:
How to make this automatically, in order to make each month comparable with the previous? I thought about some DAX formula involving a sum with filtering current month minus 1, I don’t know how to do it.
Any ideas?
UPDATE (07/08/2017)
I tried what Rasmus Dybkjær suggested me, and I thing I'm in the right path.
APPROVED_RATE_PREVIOUS_MONTH = CALCULATE([APPROVED_RATE_CURRENT_MONTH];PARALLELPERIOD(dCalendario[DataBase];-1;MONTH))
However, it returned the approved rate from the previous month as a whole (67,0% in May), not each day as I wanted:
Any suggestions?
You should be able to use the DAX function called PARALLELPERIOD() for this purpose. The PARALLELPERIOD() function takes a date column and shifts it a number of periods back or forward.
For example, you could use it like this to calculate your approved rate shifted one month back:
ApprovedRateLM =
CALCULATE(
DIVIDE(
SUM(database[QT_APRV]),
SUM(database[QT_TOTAL])
),
PARALLELPERIOD(database[Date],-1,month)
)
Note that it is important that your [Date] column contains a date type. Otherwise the PARALLELPERIOD function will not work.

Dax Calculation with logic in power bi data analytics

Need help in Data Analytics Calculations.
Currently, I am getting historical data for consumption as follows:
on above data, I am adding custom columns for calculating exact consumption(gallons) in no. of days. like:
Now, I have to plot month wise bar chart for consumption of respective Meter ID in 2016 year. But problem here is, I will have to calculate Every months consumption by dividing it in days in each respective month of 2016, and then only I will able to plot them monthly like:
y axis = consumption in every month
x axis = Jan Feb March Apr May Jun Jul Aug Sep Oct Nov Dec
so, in jan month, consumption should be = 10 + 100 + ((115/38) * 7) gallons
Notes: here, in ((115/38) * 7) : we are calculating avg consumption of single day 7 days in Jan and whole march and then getting last 7 day consumption of Jan so that we can add it in calculation of total consumption of Jan month
but how to add measure/custom column/new table for these calcualtions?
Thanks
What you need to do is relatively complicated, but the summary of my solution is:
Calculate the per-day consumption
Calculate the start and end date of each reading (e.g. the previous reading date plus one day, and the reading date)
Expand your data to have 1 row per day rather than 1-row per reading
You want to do these steps before you load the data into your data model (i.e. in your source system, or as the data is loaded using the Query Editor/Power Query).
Below, I assume you're using the Query Editor/Power Query. However, if you can use your source system, it's often the better choice (since the source system may be a database that is vastly faster than your desktop).
Note that your No. of Days calculation doesn't make sense to me. There are more than 38 days between 24 Jan 2016 and 31 Mar 2016. There are also more than 13 days between 10 Jan and 24 Jan. For this reason, it was difficult to tell whether you wanted a new reading to count on the day the previous reading was taken, or on the next full day. I assume the former. Also note, I've proceeded on the basis that your No. of Days calculation is correct
Calculate the Per Day Consumption
This is the easiest step, given that you have already calculated the Consumption and the No. of Days. Just divide one by the other. In the Query Editor, you can click in the Consumption (gallons) column and select Add Column > Standard > Divide. Under Value, choose Use values in a column and then select the No. of Days column.
Calculate the Start & End Date of Each Reading
The date of the reading is the end date, so you can rename Date to be End Date (since a reading is applied retroactively).
For the start date, in the Query Editor, you will need to add an index column (Add Column > Index Column). You will want to make sure your data is sorted by Meter ID and Date Ascending before doing this. Call the column Index.
Next, Add Column > Custom Column and pull the reading date from the prior row. Call the new column Previous End Date for now.
// A try is necessary because we can't get the previous row if there is no previous row (we'll get an error, which we can handle in the 'otherwise' block)
try
if
// See if the previous row is for the same Meter ID
[Meter ID] = #"Reordered Columns"{[Index] - 1}[Meter ID]
then
// If it is, grab the Reading Date from the previous row
#"Reordered Columns"{[Index]-1}[End Date]
else
// If this is the first reading for a meter, calculate the Start Date by subtracting the No. of Days from the End Date
Date.AddDays([End Date], -[No. of Days])
otherwise
// If this is the first row in the table, also calculate the Start Date by subtracting the No. of Days from the End Date
Date.AddDays([End Date], -[No. of Days])
Next, you'll want to add 1 to the Start Date, as we want the reading to apply to the day after the previous reading, not on the day of the previous reading.
Note, if you want the reading date to count in the prior period, subtract 1 from the End Date rather than add 1 to the start date (previous end date).
Expand your data to have 1 row per day
At this point, you should have a Meter ID, Start Date, End Date, and per day consumption column that reflects what you expect (i.e. the per day consumption is correct for the date range).
The final step is to duplicate each row for each date in the date range. There are several solutions to this outlined in this thread (https://community.powerbi.com/t5/Desktop/Convert-date-ranges-into-list-of-dates/td-p/129418), but personally, I recommend the technique (and video) posted by MarcelBeug (https://youtu.be/QSXzhb-EwHM).
You should end up with something more like this (after some removing & renaming of columns):
Finally
Now that you have one row per meter & date, with a per day consumption already calculated, you can build a visual. For example, you could do a column chart with Date on the Axis, and Consumption per Day as the value. By default, Power BI will recognize that Date is a date, and will roll it up by Year-Quarter-Month-Day. Press the little 'x' by Year and Quarter, and you'll have a chart that sums up the per day consumption by month. You can also drill down to individual date.
Further Reading
Reading a value from a previous row in Power Query
If Statements in Power Query
The AddDays function in Power Query
Adding Comments in Power Query
Catching Errors in Power Query
Converting a date range into a list of dates (Marcel Beug's solution)
A similar problem I previously answered