Forum Discussion
From one record to multiple records (enumerate dates)
Hello there,
I am a beginner in Power BI.
I have a membership table (from Dynamics), and need to do reporting on it. Users will for example ask "How many members of this type do I have in 2021?".
We have multi year membership also (1-6 years). So in the table we have "date begin", "date end".
For the user to be able to ask for a specific year, as far as I know, I need to have multiple lines for each multi-year membership.
In the past I would do this in access, and create a new table. For example, a member from 2018 to 2022 will have 5 lines, one for each year. As access has more and more problems, I have to stop using it.
How can I do the same in PowerBI? I basically need to enumerate each year between "date begin" and "date end", then add a line for each year.
Example:
Source
membership1 01-01-2018 01-12-2022
Destination
membership1 2018
membership1 2019
membership1 2020
membership1 2021
membership1 2022
Thanks in advance for your time.
PS: this is the first of about a 100 queries I need to do for my membership reporting. Should I ask my management for an SQL server to do the SQL part before sending to PowerBI? From what I have seen online, some really simple things in SQL seems to be completely arcane in Power query.
Regards,
Benjamin.
kazuma6666 This looks to me like Blowout! Blowout! - Microsoft Power BI Community
Hi kazuma6666 ,
The answer to your explicit question of how to split out year rows is this: create a new custom column in Power Query and add this as the calculation:
{Date.Year([startDate])..Date.Year([endDate])}Expand the resulting list to new rows and it should duplicate rows for each year covered.
However, the answer to your tacit question is this: You don't need to split out anything into year rows. You need to create a proper calendar table, use this to slice your report for, say, year, then write measures that count the distinct number of memberID's where [startDate] <= MIN(calendar[Date]) and [endDate] >= MAX(calendar[Date]).
There's a bit more to it than this depending on exactly how you want to report, but this is the correct way to leverage Power BI's skills, not by duplicating data rows.
Pete
Hello again 🙂
For this example, you won't have a relationship between your calendar table and your fact table.
Your measures should look something like this:
This measure will count a membership as being active within your selected timeframe if it has been active AT ANY POINT within that timeframe:
_noofActiveMemberships_Partial = CALCULATE( DISTINCTCOUNT(factTable[membershipID]), FILTER( factTable, factTable[startDate] <= MAX(calendar[date]) && factTable[endDate] >= MIN(calendar[date]) ) )This measure will only count a membership as being active if it spans the ENTIRE timeframe:
_noofActiveMemberships_Complete = CALCULATE( DISTINCTCOUNT(factTable[membershipID]), FILTER( factTable, factTable[startDate] <= MIN(calendar[date]) && factTable[endDate] >= MAX(calendar[date]) ) )Use the timeframes ([Year], [Month], [Date] etc.) from your calendar table in your visuals along with these measures and it should do what you need.
Pete
I think you may need to review your relationships and see if you can reasonably update this table to a MANY type.
This is now essentially a fact table, so would not be expected to operate as the ONE side of any relationships.
Pete
Ok, the relationship itself seems fine.
Check that your calendar table spans all the dates in your fact table and vice versa.
Check that you have marked your calendar table as the date table for the model (right-click calendar in field list and go to 'Mark as date table').
Check that your calendar table has been properly created and contains a contiguous list of dates as the [Date] column.
Double-check that you are using the Calendar[Year] column correctly in your slicer.
Beyond this, I would probably need to look at the actual PBIX itself to troubleshoot as could be one of a hundred little variables causing the issue.
Pete
TA DA!
Your [SubsDateList] data type is wrong. You have it set as Text, but you need to change it in Power Query to Date type.
When you have finished building your queries in PQ, ALWAYS ALWAYS ALWAYS go through all of your table columns and assign them the correct data type.
For example, your calendar table is almost completely untyped columns.
Go through all of your query columns and, where you see ABC123, click on this little icon and select the correct data type before applying back to the model. It will save you (and possible me!) a billion headaches in future!
Pete
33 Replies
- BA_PeteSuper User
Hi kazuma6666 ,
The answer to your explicit question of how to split out year rows is this: create a new custom column in Power Query and add this as the calculation:
{Date.Year([startDate])..Date.Year([endDate])}Expand the resulting list to new rows and it should duplicate rows for each year covered.
However, the answer to your tacit question is this: You don't need to split out anything into year rows. You need to create a proper calendar table, use this to slice your report for, say, year, then write measures that count the distinct number of memberID's where [startDate] <= MIN(calendar[Date]) and [endDate] >= MAX(calendar[Date]).
There's a bit more to it than this depending on exactly how you want to report, but this is the correct way to leverage Power BI's skills, not by duplicating data rows.
Pete
- kazuma6666Helper II
Thanks for the answer. Especially the explanations about a calendar table. I much prefer finding the correct way to do this instead of just doing the way I always did it.
I have no more time today, but will try to implement this Thursday.
- kazuma6666Helper II
Hello again BA_Pete ,
I'm trying to get your second solution working. I have created a date table (using this explanation: https://blog.crossjoin.co.uk/2013/11/19/generating-a-date-dimension-table-in-power-query/). If I understand right, I should use these dates for my CountMembers measure. I am not sure what to use for my measure in this case.
I think what the measure needs to do is look at the input date, and output all the members who have this date between [date begin] and [date end] of their membership. Is that what's needed, or did I miss something?
Is there a specific function I can use that does that?
Thanks in advance for your time!
PS: If you have a link to an explanation/tutorial about this, that would be perfect too!
PPS: Should I create a new topic for this question?
- BA_PeteSuper User
Hello again 🙂
For this example, you won't have a relationship between your calendar table and your fact table.
Your measures should look something like this:
This measure will count a membership as being active within your selected timeframe if it has been active AT ANY POINT within that timeframe:
_noofActiveMemberships_Partial = CALCULATE( DISTINCTCOUNT(factTable[membershipID]), FILTER( factTable, factTable[startDate] <= MAX(calendar[date]) && factTable[endDate] >= MIN(calendar[date]) ) )This measure will only count a membership as being active if it spans the ENTIRE timeframe:
_noofActiveMemberships_Complete = CALCULATE( DISTINCTCOUNT(factTable[membershipID]), FILTER( factTable, factTable[startDate] <= MIN(calendar[date]) && factTable[endDate] >= MAX(calendar[date]) ) )Use the timeframes ([Year], [Month], [Date] etc.) from your calendar table in your visuals along with these measures and it should do what you need.
Pete
- Greg_DecklerCommunity Champion
kazuma6666 This looks to me like Blowout! Blowout! - Microsoft Power BI Community
- kazuma6666Helper II
Thanks for your solution. It is now implemented (the simple version) and works perfectly 🙂
I also accepted your solution, but I'm a real beginner in PowerBI. I could not test it, as I don't really know how to use it right now. I'll learn at some point.
- kazuma6666Helper II
hello again,
I have come back to this project, but for some reason my custom column
{Date.Year([startDate])..Date.Year([endDate])}gives me an error now. This is the error:
Expression.Error: A cyclic reference was encountered during evaluation.
this is the line that gives the error:
= Table.AddColumn(#"Renamed Columns3", "year_membership", each {Date.Year(si_membershipsubscribers[creation date])..Date.Year(si_membershipsubscribers[Valid to])})Does anyone have an idea why this doesn't work anymore?
Thanks in advance!
- kazuma6666Helper II
I have found the reason for the cyclic error. I need to do this before renaming or reordering columns, otherwise it gives me the error.
Just in case someone else has the error.
- BA_PeteSuper User
Kudos for keeping the thread updated with your findings to help others in the future. Good job 🙂
Pete