Forum Discussion

SuraMan's avatar
SuraMan
Icon for Advocate II rankAdvocate II
7 years ago
Solved

Snapshot fact table, Count Active measures

Hello,

Is there a recommended 'Power BI' way to address the below requirement?

Business process:

1) Members can subscribe to topics and unsubsribe from topics.
    Event dates of subscribing and unsubscribing of topics are recorded

Reporting and Analytical requirements:

1) List of all topics subscribed by a member on a selected date.

2) Plot the change of the subscribed topic count of a member over time
ie. X axis= Time, Y axis= Count of topics subscribed

3) List the popularity of all topics at a given date
ie. For a given date, list the topics in the order of the highest to the lowest subscription by members

4) Plot the change of the popularity of a topic over time
ie X axis= Time, Y axis= Count of members subscribed to a given topic

There are "Member" and "Topic" tables (Dimensions).
"Fact Topic subscription" table structure that I am thinking of is:

Member ID

Topic ID

Subscribed date

Unsubscribed date

A01

Books

2017-01-01

2017-01-20

A01

Games

2018-05-01

NULL

A01

Books

2017-05-05

NULL

Is this the correct approach?

I cannot figure out a straight forward way to address the above reporting requirements because of the active and inactive nature of the topic subscription and unsubscription.

How should the "Fact Topic Subscription" table be modelled in Power BI? After that, how to write the relevant measures? Simple SUM() measures will not be correct because subscriptions can be active or inactive at a given date. If the selected date falls between "subscribed date" and "unsubscribed date" of a fact table record, then the topic subscription is active and needs to be counted for that date.

Your help is appreciated.

Thanks

 

  • So the only change I would suggest to your fact table is to insert a high end date like "31-Dec-9999" instead of null when there is no Unsubscribed Date (it just makes the logic simpler.

     

    Then if you create a date table (which is unreated to your fact) you can build measures with the following pattern

     

    Topic Cnt = 
        CALCULATE( 
            COUNTROWS('Fact Topic subscription')
            , filter('Fact Topic subscription', MAX('Date'[Date]) >= 'Fact Topic subscription'[Subscribed date] 
                                             && MIN('Date'[Date]) < 'Fact Topic subscription'[Unsubscribed date] )
        )

    You can see in the screenshot below how this picks up the end subscription of the first row and the start of the second row. (you can choose to include the Unsubscribed date in the range by changing the filter statement). You can then add addition Year, Month, Quarter, etc attributes in your Date table and the same measures should continue to work.


  • SuraMan wrote:

    Hi d_gosbell ,

    I can understand that what needs to happen is to count Fact table rows where Date[date] falls between "Subscribed date" and "Unsubscribed date", but cannot figure out how that translates to the dax expression.

    Because the 2 tables do not have a relationship between them if we just did a measure with COUNTROWS('Fact topic subscription') it would return a value of 3 for every date (as there are 3 rows in the example fact table). This is because without a relationship the 'Date' table will not filter the fact table at all.

     

    So the expression pretty much works exactly how you've described it above to filter the fact table.

     

    Topic Cnt = 
       CALCULATE( 
         COUNTROWS('Fact Topic subscription')                                    // Count the rows in the fact table
          , filter('Fact Topic subscription',                                    // filtering the fact table
    MAX('Date'[Date]) >= 'Fact Topic subscription'[Subscribed date] // where the date is after Subscribed Date && MIN('Date'[Date]) < 'Fact Topic subscription'[Unsubscribed date] ) // and before the Unsubscribed Date )

    The only "trick" is the MIN('Date'[Date])  and MAX('Date'[Date]) references. When you are at the grain of a single day these both return the same value. But if you had months on the rows the MIN would return the first day of the month and the MAX would return the last day of the month.

     

    Is the MIN/MAX the bit that made it hard to understand?

13 Replies

  • So the only change I would suggest to your fact table is to insert a high end date like "31-Dec-9999" instead of null when there is no Unsubscribed Date (it just makes the logic simpler.

     

    Then if you create a date table (which is unreated to your fact) you can build measures with the following pattern

     

    Topic Cnt = 
        CALCULATE( 
            COUNTROWS('Fact Topic subscription')
            , filter('Fact Topic subscription', MAX('Date'[Date]) >= 'Fact Topic subscription'[Subscribed date] 
                                             && MIN('Date'[Date]) < 'Fact Topic subscription'[Unsubscribed date] )
        )

    You can see in the screenshot below how this picks up the end subscription of the first row and the start of the second row. (you can choose to include the Unsubscribed date in the range by changing the filter statement). You can then add addition Year, Month, Quarter, etc attributes in your Date table and the same measures should continue to work.

    • SuraMan's avatar
      SuraMan
      Icon for Advocate II rankAdvocate II

      Hi d_gosbell ,

      Thank you for your response.

      Can you please help me understand how the measure Topic Cnt produces the correct result?

      I can understand that what needs to happen is to count Fact table rows where Date[date] falls between "Subscribed date" and "Unsubscribed date", but cannot figure out how that translates to the dax expression.

      Thanks

      • d_gosbell's avatar
        d_gosbell
        Icon for Super User rankSuper User

        SuraMan wrote:

        Hi d_gosbell ,

        I can understand that what needs to happen is to count Fact table rows where Date[date] falls between "Subscribed date" and "Unsubscribed date", but cannot figure out how that translates to the dax expression.

        Because the 2 tables do not have a relationship between them if we just did a measure with COUNTROWS('Fact topic subscription') it would return a value of 3 for every date (as there are 3 rows in the example fact table). This is because without a relationship the 'Date' table will not filter the fact table at all.

         

        So the expression pretty much works exactly how you've described it above to filter the fact table.

         

        Topic Cnt = 
           CALCULATE( 
             COUNTROWS('Fact Topic subscription')                                    // Count the rows in the fact table
              , filter('Fact Topic subscription',                                    // filtering the fact table
        MAX('Date'[Date]) >= 'Fact Topic subscription'[Subscribed date] // where the date is after Subscribed Date && MIN('Date'[Date]) < 'Fact Topic subscription'[Unsubscribed date] ) // and before the Unsubscribed Date )

        The only "trick" is the MIN('Date'[Date])  and MAX('Date'[Date]) references. When you are at the grain of a single day these both return the same value. But if you had months on the rows the MIN would return the first day of the month and the MAX would return the last day of the month.

         

        Is the MIN/MAX the bit that made it hard to understand?