Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Earn the coveted Fabric Analytics Engineer certification. 100% off your exam for a limited time only!

Reply
AlexBarnett
Regular Visitor

Advanced filter experience: "AND", "OR" , "NOT" filter logic using slicer visuals and DAX!!

Overview

There are a number of examples that have shown how to add logic so that you can use filters with an "AND" operator rather than the standard "OR" logic when using a slicer. This example shows how to also add the ability for a "NOT" statement as well, to create what I think is an incredibly powerful level of flexibility for end users.

 

AlexBarnett_0-1606341448741.png

 

 

The attached example has been built using open data and shows how the approach works

Download PBIX example 

 

Limitations - slow performance with large datasets

I am looking for help and suggestions on how to improve performance of these measures using DAX Studio or by re-engineering the approach. In my actual report the tables have millions of rows and performance is slow, the current approach results in a very large number of engine queries and depending on capacity in Power BI server can even result in visuals timing out due to lack of memory.

 

How it works (be warned, it may get confusing...)

I won't go over the full extent of how to implement AND filter logic. The approach I have used is based on the following excellent blog post.

Power BI: Implement AND/OR Selection | by ZhongTr0n | Towards Data Science

 

In my example, I have extended the logic to also allow users to EXCLUDE items. The core logic is the same, and the EXCLUSION criteria can be applied using either an OR logic or AND logic operator (i.e. Filter for Items that DON'T  have X OR Y attribute versus Items that DONT have X AND Y attribute)

 

1. If the attribute slicer is filtered, the measure below either counts the number of distinct items in the attribute list (if using an AND logic) or returns a 1 if using the OR logic

 

 

AndOrLogicSwitch (NOT) = IF (
    ISFILTERED ( 'LSOA Attributes - Filter (NOT)'[Attribute] ),
    IF (
        SUM ( 'ANDOR_Table (NOT)'[Binary] ) = 0,
        CALCULATE (
            DISTINCTCOUNT ( 'LSOA Attributes - Filter (NOT)'[Attribute] ),
            ALL ( 'LSOA Master')
        ),
        1
    ),
    CALCULATE (
        DISTINCTCOUNT ( 'LSOA Attributes - Filter (NOT)'[Attribute] ),
        ALL ( 'LSOA Master')
    )
)

 

 

 

2. A further measure then compares, for each item in the master table, the number of attributes the item has compared to the measure value. If the item has fewer attributes than the number of attributes in the above measure, then it does NOT meet the exclusion criteria and is therefore included. This is also combined with similar logic for the INCLUSION criteria, which is essentially the same logic but in reverse.

 

 

ANDORNOT Logic = 
VAR ANDORCondition = [AndOrLogicSwitch]
VAR NOTCondition = [AndOrLogicSwitch (NOT)]

VAR Include =

    and(
// This logic determines if the item meets the INCLUDE criteria
        or(not(isfiltered('LSOA Attributes - Filter'[Attribute])),DISTINCTCOUNT ( 'LSOA Attributes - Filter'[Attribute]) >= ANDORCondition)

// This logic determines if the item meets the EXCLUDE criteria
        , or(not(isfiltered('LSOA Attributes - Filter (NOT)'[Attribute])),DISTINCTCOUNT ( 'LSOA Attributes - Filter (NOT)'[Attribute] ) < NOTCondition))
RETURN
    Include

 

 

 

 

3. Further measures can then be calculated, using this logic to filter the master table, for example

 

 

Count of LSOAs = 
var LSOACount = countrows(filter('LSOA Master',[ANDORNOT Logic]))
return
LSOACount

 

 

 

Hopefully this will be helpful to others, and I would be very grateful for any ideas on how to improve on what I have done, particularly to improve performance for larger datasets.

 

Thank you

 

Alex

1 REPLY 1
PaulPalma
Frequent Visitor

@AlexBarnett 

 

Taking a high level review of your data model, I recommend you consider eliminating the bidirection relationships where possible.

It seems that you should convert your filtering Attribute tables to dimension tables. This can done by making the "..Viz" table the main Fact Table then summarizing the filtering table by adding a Group By Transformation in the M Query to each filtering table. Your relationship should need be direction between the attribute filtering table and your "...Viz" fact table. This would eliminate bidirectional relationship and reduce table size thus reducing the number of rows for iteration. In your sample data this would reduce rows from 400k to 8k.

 

An observation by using this AND/OR filtering technigue through DAX expression in the measure, you maybe adding table filter iterations through the process so may need to evaluate the benefits.

 

As a general performance improvement strategy is to minimize the number of table row scans in the execution.

 

Best regards

Paul

 

 

 

Helpful resources

Announcements
April AMA free

Microsoft Fabric AMA Livestream

Join us Tuesday, April 09, 9:00 – 10:00 AM PST for a live, expert-led Q&A session on all things Microsoft Fabric!

March Fabric Community Update

Fabric Community Update - March 2024

Find out what's new and trending in the Fabric Community.

Top Solution Authors