Forum Discussion

xl0911's avatar
xl0911
Icon for Helper III rankHelper III
4 years ago
Solved

Product table and subscription table

expected result

 

 

Hello,

 

I have a product table that looks like that:

 

Product Id      Product Name      
1Product Y
2Product X
3Product Z

 

And I have a Subscription Product Status table that a product can be in Status "Active" or "Not Active".

 

Table Id (Unique)      Product Id       Status              Status Date              
11Active20/01/2018
21Not Active23/01/2018
32Active28/01/2018
43Active14/05/2018
51Active06/03/2019
61Not Active12/08/2019
73Not Active24/02/2020
81Active06/06/2020
92Not Active22/12/2021
103Active02/03/2022

 

As you can see this Subscription Status Table holds the historical status of every product, and every row represents a status change.

 

My goal is eventually to create a visual that shows Every month the number of Active products that I had.
I need a formula to create a measure to achieve this goal.


 Thank you

  • I have updated the solution as requested to only check if the product was still active at the end of the month. (Originally you implied you wanted active anytime of the month) 

    Click here to download a solution 

     

    Now please click thumbs up and accept as solution.
    It is not fair to keep changing to problem description.
    If we the fix the problem then please accept the solution and raise a new ticket if you want to change the problem description.

     

    WasActive =
    // This measure returns a TRUE if the product was still active at the begining of the period
    VAR mindate = MIN('Calendar'[Date])
    VAR maxdate = MAX('Calendar'[Date])
    VAR previousid =
    CALCULATE(
        MAX(Facts[Table Id]),
        ALL(Facts[Status Date]),
        Facts[Status Date] < mindate)
    VAR previousstatus  =
    CALCULATE(
        SELECTEDVALUE(Facts[Status]),
        ALL(Facts),
        Facts[Table Id] = previousid)
    RETURN
    IF(previousstatus = "Active", TRUE())
     
    IsActive =
    // This measure returns
    // a TRUE if the product was set active at the end of the period
    // a FALSE if the product was set not active at the end of the period
    // the previous months valued if it was not set this month
    VAR mindate = MIN('Calendar'[Date])
    VAR maxdate = MAX('Calendar'[Date])
    VAR lastid =
    CALCULATE(
        MAX(Facts[Table Id]),
        ALL(Facts[Status Date]),
        Facts[Status Date] >= mindate && Facts[Status Date] <= maxdate)
    VAR laststatus  =
    CALCULATE(
        SELECTEDVALUE(Facts[Status]),
        ALL(Facts),
        Facts[Table Id] = lastid)
    RETURN
    SWITCH(TRUE(),
    laststatus = "Active", TRUE(),
    laststatus = "Not Active", FALSE(),
    [WasActive]
    )
     
     
    ActiveProducts =
    // This measure counts the number or products that were active

    SUMX(
        VALUES(Products[Product Id]),
        INT([IsActive])
    )
     

46 Replies

  • Sorry @tamerj1, I think there is a bug in your DAX

    Only one product was active in Feb 2018 but your report shows two.

    Thanks for trying to help xl0911

    Please can you double check my solution (see above).
    Two pairs of eyes are better than one.

     

  •  @xl0911  I have accepted my solution because I proivided  2 solutions that worked but you keep changing the problem description.

     

    In future when you raise a problem, please show your thanks to volunteers who help with a thumb click and accept the solution.  One question per ticket please. If you need to extend your request then please raise a new ticket.

    You will get a quicker response and each volunteer solver will get the kudos they deserve. Thank you ! 

     

     

  • tamerj1's avatar
    tamerj1
    Icon for Community Champion rankCommunity Champion

    Hi xl0911 
    Here is the a sample file with the solution https://we.tl/t-RX6Wox2KRZ

     

    # Active Subscriptions = 
    SUMX (
        VALUES ( Products[Product Id] ),
        CALCULATE (
            VAR CurrentDate = 
                MAX ( 'Date'[Date] )
            VAR PreviousTable = 
                FILTER ( Subscription, Subscription[Status Date] <= CurrentDate )
            VAR PreviousActiveTable = 
                FILTER ( PreviousTable, Subscription[Status] = "Active" )
            VAR LastActivation = 
                MAXX ( PreviousActiveTable, Subscription[Status Date] )
            VAR PreviousIactctiveTable = 
                FILTER ( PreviousTable, Subscription[Status] <> "Active" && Subscription[Status Date] > LastActivation )
            VAR LastInactivation = 
                COALESCE ( MAXX ( PreviousIactctiveTable, Subscription[Status Date] ), DATE ( 3000, 1, 1 ) )
            RETURN
                IF ( 
                    CurrentDate <= LastInactivation && CurrentDate >= LastActivation,
                    1
                )
        )
    )

     

    • xl0911's avatar
      xl0911
      Icon for Helper III rankHelper III

      Thank you tamerj1,

       

      Two things please:

      1. In my original schema my date table  already has relationship, so I guess I need to add USERELATIONSHIP function (but I dont know where to add it)

      2. It seams that the result I'm getting is not in "running total", I'm sorry that i wasn't more clear.

      • tamerj1's avatar
        tamerj1
        Icon for Community Champion rankCommunity Champion

        Hi xl0911

        it is running total but you need to CROSSFILTER the relationship to NONE

  • Thank you  xl0911 for a very clear explantion of your problem with example data as tables (not screen shots).
    So I could import the data and build this solution. Wish all members gave such clear decsriptions!

    Click here to download the solution  

     

    Quote speedramps when you raise new problems if you can describe them all as nicely as this and I will receive an notification.

     

     

    I created 3 measures

     

     

    WasActive =
    // This measure returns a TRUE is the product was still active at the begining of the period
    VAR mindate = MIN('Calendar'[Date])
    VAR maxdate = MAX('Calendar'[Date])
    VAR previousid =
    CALCULATE(
        MAX(Facts[Table Id]),
        ALL(Facts[Status Date]),
        Facts[Status Date] < mindate)
    VAR previousstatus  =
    CALCULATE(
        SELECTEDVALUE(Facts[Status]),
        ALL(Facts),
        Facts[Table Id] = previousid)
    RETURN
    IF(previousstatus = "Active", TRUE())
     
    IsActive =
    // This measure returns a TRUE is the product was set to active at any time duting the period
    VAR mindate = MIN('Calendar'[Date])
    VAR maxdate = MAX('Calendar'[Date])
    VAR activethisperiod =
    CALCULATE(
        SELECTEDVALUE(Facts[Status]),
        ALL(Facts[Status Date]),
        Facts[Status Date] >= mindate && Facts[Status Date] <= maxdate,
        Facts[Status] = "Active")
    RETURN
    IF(activethisperiod = "Active", TRUE())
     
    ActiveProducts =
    // This measure counts the number or products that were either active at the begining of the period or were set to active during the period
    SUMX(
        VALUES(Products[Product Id]),
        INT( [IsActive] || [WasActive])
    )
     
     
    My report shows the active products per month in the top left.
    The top right visual is an audit trail to help with testing. 
    The bottom righ is your source data.
    If you clcic a product in the audit report them the source data will filter accordingly to help with testing. 
     
    • xl0911's avatar
      xl0911
      Icon for Helper III rankHelper III

      Thank you speedramps

       

      I think your solution is not what I meant because Product Id 1 is not active in the end of the month so under product Id 1 in jan-2018 the count should be 0.

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

        I have updated the solution as requested to only check if the product was still active at the end of the month. (Originally you implied you wanted active anytime of the month) 

        Click here to download a solution 

         

        Now please click thumbs up and accept as solution.
        It is not fair to keep changing to problem description.
        If we the fix the problem then please accept the solution and raise a new ticket if you want to change the problem description.

         

        WasActive =
        // This measure returns a TRUE if the product was still active at the begining of the period
        VAR mindate = MIN('Calendar'[Date])
        VAR maxdate = MAX('Calendar'[Date])
        VAR previousid =
        CALCULATE(
            MAX(Facts[Table Id]),
            ALL(Facts[Status Date]),
            Facts[Status Date] < mindate)
        VAR previousstatus  =
        CALCULATE(
            SELECTEDVALUE(Facts[Status]),
            ALL(Facts),
            Facts[Table Id] = previousid)
        RETURN
        IF(previousstatus = "Active", TRUE())
         
        IsActive =
        // This measure returns
        // a TRUE if the product was set active at the end of the period
        // a FALSE if the product was set not active at the end of the period
        // the previous months valued if it was not set this month
        VAR mindate = MIN('Calendar'[Date])
        VAR maxdate = MAX('Calendar'[Date])
        VAR lastid =
        CALCULATE(
            MAX(Facts[Table Id]),
            ALL(Facts[Status Date]),
            Facts[Status Date] >= mindate && Facts[Status Date] <= maxdate)
        VAR laststatus  =
        CALCULATE(
            SELECTEDVALUE(Facts[Status]),
            ALL(Facts),
            Facts[Table Id] = lastid)
        RETURN
        SWITCH(TRUE(),
        laststatus = "Active", TRUE(),
        laststatus = "Not Active", FALSE(),
        [WasActive]
        )
         
         
        ActiveProducts =
        // This measure counts the number or products that were active

        SUMX(
            VALUES(Products[Product Id]),
            INT([IsActive])
        )
         
  • tamerj1's avatar
    tamerj1
    Icon for Community Champion rankCommunity Champion

    Hi xl0911 
    Here is the updated solution with active relationship with the date table and fixed the bug noticed by speedramps 

    https://we.tl/t-NlQUK1FT2T

    # Active Subscriptions = 
    SUMX (
        VALUES ( Products[Product Id] ),
        CALCULATE (
            VAR PeriodStartDate = 
                MIN ( 'Date'[Date] )
            VAR PeriodEnadDate = 
                MAX ( 'Date'[Date] )
            VAR TableBeforePeriodEnd = 
                FILTER ( Subscription, Subscription[Status Date] <= PeriodEnadDate )
            VAR PreviousActiveTable = 
                FILTER ( TableBeforePeriodEnd, Subscription[Status] = "Active" )
            VAR LastActivation = 
                COALESCE ( MAXX ( PreviousActiveTable, Subscription[Status Date] ), DATE ( 3000, 1, 1 ) )
            VAR TableBeforePeriodStart = 
                FILTER ( Subscription, Subscription[Status Date] < PeriodStartDate )
            VAR PreviousIactctiveTable = 
                FILTER ( TableBeforePeriodStart, Subscription[Status] <> "Active" )
            VAR LastInactivation = 
                COALESCE ( MAXX ( PreviousIactctiveTable, Subscription[Status Date] ), DATE ( 3000, 1, 1 ) )
            VAR Result =
                IF ( 
                    PeriodEnadDate >= LastActivation && PeriodStartDate <= LastInactivation,
                    1
                )
            RETURN
                Result,
            CROSSFILTER ( 'Date'[Date], Subscription[Status Date], None )
        )
    )

    I wanted to upload more screenshots but seems I reached my maximum allowable limit of uploaded images!

    • xl0911's avatar
      xl0911
      Icon for Helper III rankHelper III

      Thank you.

      I'm getting this error "The expression refers to multiple columns. Multiple columns cannot be converted to a scalar value."

       

      I guess that maybe the formula can't handle a scenario that maybe a product has 2 rows of status in the same date... ? 

       

       

    • xl0911's avatar
      xl0911
      Icon for Helper III rankHelper III

      I think your solution is not what I meant because Product Id 1 is not active in the end of the month so under product Id 1 in jan-2018 the count should be 0.

  • tamerj1's avatar
    tamerj1
    Icon for Community Champion rankCommunity Champion

    Hi xl0911 
    This version is working perfectly in the sample file. Please download the sample file and compare with yours. https://we.tl/t-c14Wj8tpax

    # Active Subscriptions = 
    SUMX (
        VALUES ( Products[Product Id] ),
        CALCULATE (
            VAR PeriodEnadDate = 
                MAX ( 'Date'[Date] )
            VAR TableBeforePeriodEnd = 
                FILTER ( Subscription, Subscription[Status Date] <= PeriodEnadDate )
            VAR PreviousActiveTable = 
                FILTER ( TableBeforePeriodEnd, Subscription[Status] = "Active" )
            VAR LastActivation = 
                COALESCE ( MAXX ( PreviousActiveTable, Subscription[Status Date] ), DATE ( 3000, 1, 1 ) )
            VAR PreviousIactctiveTable = 
                FILTER ( TableBeforePeriodEnd, Subscription[Status] <> "Active" && Subscription[Status Date] > LastActivation )
            VAR LastInactivation = 
                COALESCE ( MAXX ( PreviousIactctiveTable, Subscription[Status Date] ), DATE ( 3000, 1, 1 ) )
            VAR Result =
                IF ( 
                    PeriodEnadDate >= LastActivation && PeriodEnadDate <= LastInactivation,
                    1
                )
            RETURN
                COALESCE ( Result, 0 ),
            CROSSFILTER ( 'Date'[Date], Subscription[Status Date], None )
        )
    )