0

I have some table like this:

+------+------+------+
| Lvl1 | Lvl2 | Lvl3 |
+------+------+------+
| A1   | B1   | C1   |
| A1   | B1   | C2   |
| A1   | B2   | C3   |
| A2   | B3   | C4   |
| A2   | B3   | C5   |
| A2   | B4   | C6   |
| A3   | B5   | C7   |
+------+------+------+

In which it is some thing like a hierarchy.

When user select A1, he actually selects the first 3 rows, B1, selects first 2 rows, and C1, selects only the first row.

That is A is the highest level, and C is the lowest. Note that ids from different levels are unique, since they have a special prefix, A,B,C.

The problem is when filtering in more than one level, I may have empty result set.

e.g. filtering on Lvl1=A1 & Lvl2=B3 (no intersection), and so will return nothing. What I need is to get the first 5 rows (Lvl1=A1 or Lvl2=B3)

const lvl1Filter: IBasicFilter = {
  $schema: "http://powerbi.com/product/schema#basic",
  target: {
    table: "Hierarchy",
    column: "Lvl1"
  },
  operator: "In",
  values: ['A1'],
  filterType: FilterType.BasicFilter
}

const lvl2Filter: IBasicFilter = {
  $schema: "http://powerbi.com/product/schema#basic",
  target: {
    table: "Hierarchy",
    column: "Lvl2"
  },
  operator: "In",
  values: ['B3'],
  filterType: FilterType.BasicFilter
}

report.setFilters([lvl1Filter, lvl2Filter]);

The problem is that the filters are independent from each other, and they will both be applied, that is with AND operation between them.

So, is there a way to send the filters with OR operation between them, or is there a way to simulate it?

PS: I tried to put all data in single column (like the following table), and it worked, but the data was very large (millions of records), and so, it was very very slow, so I need something more efficient.

All data in single column:

+--------------+
| AllHierarchy |
+--------------+
| A1           |
| A2           |
| A3           |
| B1           |
| B2           |
| B3           |
| B4           |
| B5           |
| C1           |
| C2           |
| C3           |
| C4           |
| C5           |
| C6           |
| C7           |
+--------------+

Set Filter:

const allHierarchyFilter: IBasicFilter = {
  $schema: "http://powerbi.com/product/schema#basic",
  target: {
    table: "Hierarchy",
    column: "AllHierarchy"
  },
  operator: "In",
  values: ['A1', 'B3'],
  filterType: FilterType.BasicFilter
}

report.setFilters([allHierarchyFilter]);
Hussein Dahir
  • 395
  • 4
  • 14
  • You say *e.g. filtering on A1 & B3 (no intersection), I need to get the first 5 rows.* Could you explain why you should get top 5 rows in this case? Maybe just to describe the filter you want in plain English. – Andrey Nikolov Nov 28 '19 at 07:18
  • sorry for confusion, I meant filtering on A1 & B3 will return nothing. But what I want is to return top 5 rows, that is, I want (A1 || B3) instead of (A1 & B3), but I can't send such filter – Hussein Dahir Nov 28 '19 at 08:11

1 Answers1

0

It isn't directly possible to make "or" filter between multiple columns in Power BI, so you were right to try to combine all values in a single column. But instead of appending all possible values by union them in one column, which will give you a long list, you can also try to combine their values "per row". For example, concatenate all values in the current row, maybe add some unique separator (it depends on your actual values, which are not shown). If all columns will have values, make it simple - create new DAX column (not a measure!):

All Levels = 'Table'[Lvl1] & "-" & 'Table'[Lvl2] & "-" & 'Table'[Lvl3]

If it is possible some of the levels to be blank, you can if you want, to handle that:

All Levels = 'Table'[Lvl1] &
    IF('Table'[Lvl2] = BLANK(); ""; "-" & 'Table'[Lvl2]) &
    IF('Table'[Lvl3] = BLANK(); ""; "-" & 'Table'[Lvl3])

Note that depending on your regional settings, you may have to replace semicolons in the above code with commas.

This will give you a new column, which will contain all values from the current row, e.g. A1-B2-C3. Now you can make a filter All Levels contains A1 or All Levels contains B3, which now is a filter on a single column and we can easily use or:

enter image description here

When embedding your JavaScript code should create advanced filter, like this:

const allLevelsFilter: IAdvancedFilter = {
  $schema: "http://powerbi.com/product/schema#advanced",
  target: {
    table: "Hierarchy",
    column: "All Levels"
  },
  logicalOperator: "Or",
  conditions: [
    {
      operator: "Contains",
      value: "A1"
    },
    {
      operator: "Contains",
      value: "B3"
    }
  ],
  filterType: FilterType.AdvancedFilter
}

report.setFilters([allLevelsFilter]);

If you need exact match (e.g. the above code will also return rows with A11 or B35), then add the separator at the start and the end of the column too (i.e. to get -A1-B2-C3-) and in your JavaScript code append it before and after your search string (i.e. search for -A1- and -B3-).

Hope this helps!

Andrey Nikolov
  • 12,967
  • 3
  • 20
  • 32
  • Thank you, I didn't mention it, but I tried it at first, in fact, I have a column already created for it called Path (e.g. A1/B1/C1), and I used a AdvancedFilter with operator: "StartWith", sending the path of a selected node (e.g. A1 path is A1, B1 path is A1/B1), and it worked, but it was 20 times slower than the method I mentioned in the question above, since here we are using string operations. – Hussein Dahir Nov 28 '19 at 12:19
  • The best performance will be if you have a table with persisted column with all possible levels, relationships with your level columns and filtering this table. – Andrey Nikolov Nov 28 '19 at 17:22
  • You could also try to union the results of the filtering the table with any of the `or` values. – Andrey Nikolov Nov 28 '19 at 17:25
  • thanks again, anyway, I found that Tuple Filter can do this (make OR operation between two different columns in two different tables), check this: https://learn.microsoft.com/en-us/power-bi/developer/visuals/filter-api#the-tuple-filter-api-multi-column-filter – Hussein Dahir Dec 04 '19 at 16:24
  • but still couldn't make it run, see https://stackoverflow.com/questions/59181883/powerbi-how-to-use-tuplefilter-with-powerbi-client – Hussein Dahir Dec 04 '19 at 17:52