Counting latest instance of multiple only based on filter context

心已入冬 提交于 2020-02-25 09:49:26

问题


I've got a large table of events that have occurred in an inventory of vehicles, which affect whether they are in service or out of service. I would like to create a measure that would be able to count the number of vehicles in the various inventories at any point in time, based on the events in this table.

This table is pulled from a SQL database into an Excel 2016 sheet, and I'm using PowerPivot to try to come up with the DAX measure.

Here is some example data event_list:

vehicle_id    event_date    event         event_sequence    inventory
100           2018-01-01    purchase      1                 in-service
101           2018-01-01    purchase      1                 in-service
102           2018-02-04    purchase      1                 in-service
100           2018-02-07    maintenance   2                 out-of-service
101           2018-02-14    damage        2                 out-of-service
101           2018-02-18    repaired      3                 in-service
100           2018-03-15    repaired      3                 in-service
102           2018-05-01    damage        2                 out-of-service
103           2018-06-03    purchase      1                 in-service

I'd like to be able to create a pivot table in Excel (or use CUBE functions, etc) to get an output table like this:

date          in-service     out-of-service
2018-02-04    3              0
2018-02-14    1              2
2018-03-15    3              0
2018-06-03    3              1

Essentially, I want to be able to calculate the inventory based on any date in time. The example only has a few dates, but hopefully provides enough of a picture.

I've basically come up with this so far, but it counts more vehicles than desired - I can't figure out how to only take the latest event_sequence or event_date and use that to count the inventory.

cumulative_vehicles_at_date:=CALCULATE(
    COUNTA([vehicle_id]),
    IF(IF(HASONEVALUE (event_list[event_date]), VALUES (event_list[event_date]))>=event_list[event_date],event_list[event_date])
)

I tried using MAX() and EARLIER() functions, but they don't seem to work.

Edit: Added the PowerBI tag as I'm now using that software to attempt to solve this as well. See comments on Alexis Olson's answer.


回答1:


I think I've found a much cleaner method than I gave previously.


Let's add two columns onto the event_list table. One which counts vehicles "in-service" on that date and one which counts vehicles "out-of-service" on that date.

InService = 
    VAR Summary = SUMMARIZE(
                      FILTER(event_list,
                          event_list[event_date] <= EARLIER(event_list[event_date])),
                      event_list[vehicle_id],
                      "MaxSeq", MAX(event_list[event_sequence]))

    VAR Filtered = FILTER(event_list,
                       event_list[event_sequence] =
                           MAXX(
                               FILTER(Summary,
                                   event_list[vehicle_id] = EARLIER(event_list[vehicle_id])),
                               [MaxSeq]))

    RETURN SUMX(Filtered, 1 * (event_list[inventory] = "in-service"))

You can create an analogous calculated column for OutOfService or you can just take the total minus the InService count.

OutOfService =
    CALCULATE(
        DISTINCTCOUNT(event_list[vehicle_id]),
        FILTER(event_list,
            event_list[event_date] <= EARLIER(event_list[event_date])))
    - event_list[InService]

Now all you have to do is put event_date on the matrix visual rows section and add the InService and OutOfService columns to the values section (use Maximum or Minimum for the aggregation option rather than Sum).


Here's the logic behind the calculated column InService:

We first create a Summary table which calculates the maximal event_sequence value for each vehicle. (We filter the event_date to only consider dates up to the current one we are working with.)

Now that we know what the last event_sequence value is for each vehicle, we use that to filter the entire table down to just the rows that correspond to those vehicles and sequence values. The filter goes through the table row by row and checks to see if the sequence value matches the one we calculated in the Summary table. Note that when we filter the Summary table to just the vehicle we are currently working with, we only get a single row. I'm just using MAXX to extract the [MaxSeq] value. (It's kind of like using LOOKUPVALUE, but you can't use that on a variable.)

Now that we've filtered the table just to the most recent events for each vehicle, all we need to do is count how many of them are "in-service". I used a SUMX here where the 1*(True/False) coerces the boolean value to return 1 or 0.




回答2:


This is pretty difficult. I don't have a great answer, but here's something that kind of works.

You'll create a new calculated table where you'll calculate the status for each vehicle on each date. Start with the base cross join for each vehicle and each date:

= CROSSJOIN(VALUES(event_list[vehicle_id]), VALUES(event_list[event_date]))

Then add a calculated column to find the max sequence number for each vehicle on that date.

Sequence = MAXX(
               FILTER(event_list,
                   event_list[event_date] <= Cross[event_date] &&
                   event_list[vehicle_id] = Cross[vehicle_id]),
               event_list[event_sequence])

Now you can lookup the inventory value for each vehicle/sequence pair with another calculated column:

Inventory = LOOKUPVALUE(
                event_list[inventory],
                event_list[vehicle_id], Cross[vehicle_id],
                event_list[event_sequence], Cross[Sequence]) 

The result should look something like this:

Once you have this, you can create a matrix using this calculated table. Put the event_date on the rows and Inventory on the columns. Filter out blank inventory values in the visual level filter and put the vehicle_id in the values field, using a count or distinct count as the aggregation method (instead of the default sum).

It should look like this:



来源:https://stackoverflow.com/questions/51315009/counting-latest-instance-of-multiple-only-based-on-filter-context

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!