I am looking to calculate the sales for the SAMEPERIODLASTYEAR. I have a table which looks at the sales for the last few years and using the SAMEPERIODLASTYEAR function I can draw back to last January as a whole, but what I am wanting is to pull it to the date exactly and not to the end of the current month last year.
My formula below is pulling through for example all of January last year.
Sales Last Year:=CALCULATE([Sum of Sales],SAMEPERIODLASTYEAR(Dates[Date]))
Is there a way of doing this using just the SAMEPERIODLASTYEAR function rather than indivudual daily calculations?
I do not claim that this is the best (or only) way to do this, but how about:
Sales Last Year =
CALCULATE (
[Sum of Sales],
FILTER (
SAMEPERIODLASTYEAR ( 'Dates'[Date] ),
'Dates'[Date]
< DATE ( YEAR ( TODAY () ) - 1, MONTH ( TODAY () ), DAY ( TODAY () ) )
)
)
Essentially, I've added a FILTER() statement around the SAMEPERIODLASTYEAR clause, and filtered the results to be before the current date last year. If today is 8-Jan-2018, this means any sales on or after 8-Jan-2017 will be filtered out.
In essence, I'm taking the current date (TODAY()), breaking it down into its component parts, subtracting 1 from the year, then building it back up into a date value using the DAX DATE() function.
The reason I do this rather than using DATEADD() to subtract a year Excel-style is because DATEADD requires a table of dates as an input and TODAY() is a single date. You therefore cannot put TODAY() into DATEADD() directly.
Instead of using TODAY(), I could have a measure that identifies the most recent date for which there is data and call that instead. It's the same solution.
I'd be curious if others have a better way to do this. This strikes me as a common problem people must run into a lot.
Related
I am facing a relatively trivial problem. I have a list of start dates for each fiscal year. For example, 03.01.2019 for the 2019 financial year or 30.12.2019 for the 2020 financial year.
Now I want the calculated column in my calendar table (Power Pivot) to count up from the start date from 1-53 per week until the next start date.
It would look like this:
03.01.2019 - 1
04.01.2019 - 1 ....
Does anyone know how to do this?
You cen get the ISO 8601 weeknumbers by adding 21 in the optional part. Here a quick example I created. But if you also have dates which start in the middle of the year you should go with a calendar, like #Kosuke Sakai posted:
Generally, the recommended approach for this requirement is to prepare a fiscal calendar in the data source (DWH, MDM, Excel, or somewhere), rather than to calculate with DAX.
Having said that, it is possible with DAX.
Assuming you have a table like below. (Let's call it FiscalYears)
First, you need to add FiscalYear calculated column to your Calendar table with following formula.
FiscalYear :=
VAR CurrentDate = [Date]
RETURN CALCULATE (
MAX ( FiscalYears[FiscalYear] ),
FiscalYears[StartDate] <= CurrentDate
)
Then, you can use this to calculate WeekNumberInFiscalYear column.
WeekNumberInFiscalYear :=
VAR StartDate = LOOKUPVALUE (
FiscalYears[StartDate],
FiscalYears[FiscalYear],
[FiscalYear]
)
RETURN DATEDIFF ( StartDate, [Date], WEEK ) + 1
The result will be looking like below.
I have a table within PowerPivot currently that tracks a count of customers through our sales pipeline. From (by sales location) first interaction to charged sale. So far, I’ve creates a moving 5-day average that averages each task. Below is the DAX formula I’ve created thus far and an example table.
=
CALCULATE (
SUM ( [Daily Count] ),
DATESINPERIOD ( Table1[Date], LASTDATE ( Table1[Date] ), -7, DAY ),
ALLEXCEPT ( Table1, Table1[Sales Location], Table1[Group] )
)
/ 5
Where I’m struggling is being able to come up with a way to exclude weekends and company observed holidays. Additionally, if a holiday falls on a weekday I would like to remove that from the average and go back an additional day (to smooth the trend).
For example, on 11/26/18 (the Monday after Thanksgiving and Black Friday) I would like to average the five business days previous (11/26/18, 11/21-11/19, and 11/16). In the example above, the moving total and average for the previous 5 days should be Intake = 41 (total) 8.2 (average), Appointment = 30 (total) 6 (average), and Sale = 13 (total) and 2.6 (average).
Based on the formula currently, each of these numbers is inaccurate. Is there an easy way to exclude these days?
Side note: I’ve created an ancillary table with all holidays that is related to the sales data that I have.
Thank you for the help!
For this, I'd recommend using a calendar table related to Table1 on the Date column that also has a column IsWorkday with 1 if that day is a workday and 0 otherwise.
Once you have that set up, you can write a measure like this:
Moving Avg =
VAR Last5Workdays =
SELECTCOLUMNS (
TOPN (
5,
FILTER (
DateTable,
DateTable[Date] <= EARLIER ( Table1[Date] )
&& DateTable[IsWorkday] = 1
),
DateTable[Date], DESC
),
"Workday", DateTable[Date]
)
RETURN
CALCULATE (
SUM ( Table1[Daily Count] ),
Table1[Date] IN Last5Workdays
ALLEXCEPT ( Table1, Table1[Sales Location], Table1[Group] ),
)
/ 5
The TOPN function here returns the top 5 rows of the DateTable where each row must be a workday that is less than or equal to the date in your current Table1 row (the EARLIER function refers to the earlier row context that defines the current row).
I then use SELECTCOLUMNS to turn this table into a list by selecting a single column (which I've named Workday). From there, it's basically your measure with the date filter changed a bit.
#alexisolson Thank you for the response here. I was actually able to figure this out over the weekend but forgot to close out the thread (sorry about that! Appreciate your help either way). But I did something fairly similar to what you mentioned above.
I created a date table (CorpCalendar) that was only inclusive of working days. Then I created an index column within the CorpCalendar table to give each row a unique number in ascending order. From there, I linked the CorpCalendar table to my SalesData table by related dates and used the LOOKUPVALUE function to bring the index value over from the CorpCalendar table to the SalesData table. In a separate column I subtracted 4 from the date index value to get an index adjustment column (for a range of five days from the actual date index and the adjustment...if that makes sense). I then added an additional LOOKUPVALUE helper column to match the adjusted date index column to the appropriate working day.Lastly, I then used the following function to get the 5 day rolling average.
=CALCULATE(sum(Combined[Daily Count]),DATESBETWEEN(Combined[Date - Adjusted],Combined[Date - Adjusted (-5)],Combined[Date - Adjusted]),ALLEXCEPT(Combined,Combined[Group]))/5
This is probably more convoluted than necessary, however, it got me to the answer I was looking for. Let me know if this makes sense and if you have any suggestions for future scenarios like this.
Thanks again!
There are already plenty of options for calculating the number of workdays between two dates if there are no times involved, but if you leave it as date/time, is there any way to get a number of working days (with decimal remainders) between two points in time in DAX (e.g. Power Query/Power BI)?
Assuming that your start and end times occur on working days, then you should be able to take the time difference between two dates and subtract out the number of non-working days during that period.
You'll want a calendar table to help out. Say,
Dates = CALENDARAUTO()
Then your working days measure might look like this:
WorkingDays =
StartFinish[Finish Date] - StartFinish[Start Date] -
SUMX(
FILTER(Dates,
Dates[Date] > StartFinish[Start Date] &&
Dates[Date] < StartFinish[Finish Date]),
IF(WEEKDAY(Dates[Date]) = 1 || WEEKDAY(Dates[Date]) = 7, 1, 0)
)
If you have an IsWorkDay column in your calendar table (which might include holidays as well as weekends), you can just reference that for the last line instead:
IF(Dates[IsWorkDay], 0, 1)
Note that this approach assumes a working day is 24 hours rather than a more standard 8 hours. You'll have to make some adjustments if you don't want the fractional part to indicate the portion of 24 hours. To switch to a portion of 8 hour work days, just multiply the fractional part by 24/3 = 3.
Ive spent the last 2 days trying to get this, and I really just need a few pointers. Im using Excel 2010 w/ Power Pivot and calculating inventories. I am trying to get the amount sold between 2 dates. I recorded the quantity on hand if the item was in stock.
Item # Day Date Qty
Black Thursday 11/6/2014 2
Blue Thursday 11/6/2014 3
Green Thursday 11/6/2014 3
Black Friday 11/7/2014 2
Green Friday 11/7/2014 2
Black Monday 11/10/2014 3
Blue Monday 11/10/2014 4
Green Monday 11/10/2014 3
Is there a way to do this in dax? I may have to go back and calculate the differences for each record in excel, but Id like to avoid that if possible.
Somethings that have made this hard for me.
1) I only record the inventory Mon-Fri. I am not sure this will always be the case so i'd like to avoid a dependency on this being only weekdays.
2) When there is none in stock, I dont have a record for that day
Ive tried, CALCULATE with dateadd and it gave me results nearly right, but it ended up filtering out some of the results. Really was odd, but almost right.
Any Help is appreciated.
Bryan, this may not totally answer your question as there are a couple of things that aren't totally clear to me but it should give you a start and I'm happy to expand my answer if you provide further info.
One 'pattern' you can use involves the TOPN function which when used with the parameter n=1 can return the earliest or latest value from a table that it sorts by dates and can be filtered to be earlier/later than dates specified.
For this example I am using a 'disconnected' date table from which the user would select the two dates required in a slicer or report filter:
=
CALCULATE (
SUM ( inventory[Qty] ),
TOPN (
1,
FILTER ( inventory, inventory[Date] <= MAX ( dates[Date] ) ),
inventory[Date],
0
)
)
In this case the TOPN returns a single row table of the latest date earlier than or equal to the latest date provided. The 1st argument in the TOPN specifies the number of rows, the second the table to use, the 3rd the column to sort on and the 4th says to sort descending.
From here it is straightforward to adapt this for a second measure that finds the value for the latest date before or equal to the earliest date selected (i.e. swap MIN for MAX in MAX(dates[Date])).
Hope this helps.
Jacob
*prettified using daxformatter.com
I’m trying to work out the DAX expression [for MS PowerPivot in Excel 2010] to evenly distribute the sum of a value across the range it’s applied to, and re-sum that up for a given time span/period. It’s trivial to cross-apply in SQL server, though with every attempt, end up with the same wrong result.
I’ve got the output from MS Project saved as Excel and imported/transformed using PowerQuery, so the start and finish/end dates are proper dates, the {X}h and {Y}d are integers, and the calendar day duration between them are already calculated/formatted for the model. I also have a dates table created that has the contiguous dates from the first date through the last, and a years table that has the string representation of the 4 digit years I want to summarize by.
The model looks like so:
I have created calculated columns on the ResourceQuery, TaskQuery and AssignmentQuery tables (all directly taken from the MS Project output), and on the ServiceAreaQuery (unique values from TaskQuery … essentially subprojects). Each also has a simple measure that is the sum of the Assigned hours column.
The data itself looks like you’d expect from a Project 2010 file, and has a {start_date}, {finish_date} and hours. The dates for a task can span anywhere from 1 day to 5 years … and this is where my problem lies.
How do I split/chunk the pre-summed value for a long running tasks to match the time interval I’m looking for?
Even if I use the year column from the date table, the time intelligence doesn’t catch it & I’m running out of ideas for a CALCULATE(SUM(FILTER(COUNTROWS(DATESBETWEEN)))) type of thing.
There are two intermediate steps I've tried to figure out to no avail. I’d imagine they are both solved by the same effective function to get to the end goal of hours, by service area, by resource, by year.
Pivot table to show
Hours by resource, by year
Hours by service area, by year
in order to show the end goal of
Hours, by service area, by resource, by year
You can see the issue in the output below.
Note that when using the total of assigned hours, and the resource name from AssignmentQuery, I get the right sums, but when using any date value … I only get the hours against the start date (the active relationship in the model). What I need is for those hours to be evenly spread across the period that they’re applicable to (so if something has 1,000 hours between 1/1/16 and 1/1/19 I’d expect 333 hours/year to show).
My initial thought is that the selector/filter/calculate function needs to do the following:
Select the hours for the person
Select the days in the period filtered to (e.g. month/year/quarter/whatever) from either a filter or as a column header
Calculate the hours per day
Get the working days in the filtered period
select the sum of the hours from the overlap
Any ideas are greatly appreciated! I’m open to doing some additional ETL/data creation as a PowerQuery step, but would really like to figure out the right DAX expression for this so it can be something available as a time-slicer/filter on the project.
Thanks in advance.
** Edit to post the revised version of the answer provided **
[Hours Apportioned Raw] :=
DIVIDE (
CALCULATE (
[Hours],
FILTER (
AssignmentQuery,
AssignmentQuery[Start_Date] <= MAX ( Dates[Date] )
&& AssignmentQuery[Finish_Date] >= MAX ( Dates[Date] )
)
)
, ( COUNTROWS (
DATESBETWEEN (
Dates[Date]
, FIRSTDATE ( AssignmentQuery[Start_Date] )
, LASTDATE ( AssignmentQuery[Finish_Date] )
)
)
)
)
Given that you have a relatively complex model in place and your requirement is not totally straightforward, I'm not sure that this will get you all the way there but hopefully it will at least either give you the inspiration to modify it for your purposes or start a more detailed discussion.
The measures below effectively sum the hours, apply them to dates where the dates are between the start and end and divides the total by the number of days. The slight complexity is this needs to be iterated x2 - once over dates and once over rows in the table containing the hours.
An issue for you might be that I'm using an unconnected date table and if you can't replicate this situation in your model then we will need to try using some ALL() functions instead.
Solution below assumes a table called 'data' that has 4 columns: id, start, end, value and table called calendar that has 2 columns Date and Month.
Measure 1: Sum the hours
[Hours] =SUM(Data[Value])
Measure 2: Apply the hours to the dates and divide by number of dates
[Hours Apportioned Raw] =
CALCULATE ([Hours],
FILTER (
Data,
Data[Start] <= MAX ( Calendar[Date] )
&& Data[END] >= MAX ( Calendar[Date] )
)
)
/ ( MAX ( Data[End] ) - MAX ( Data[Start] ) )
Measure 3: Iterate Measure 2 over dates and ids to give correct values
=
SUMX (
VALUES ( Calendar[Date] ),
SUMX ( VALUES ( Data[ID] ), [Hours Apportioned RAW] )
)
Hope this makes some sense, very simple test model here: Test Model
Note you will need to download the model not just view it in the browser.