RLS doesn't work with bidirection dax in powerbi - powerbi

We are working with Power BI to create self service report and want to limit access based on login user. But it is not all that straight forward. Here's our security model:
Have 4 tables
Table1
UserID(Email) AreaID
======= ========
Email1 Area1
Email2 Area2
Email1 Area3
Email3 Area3
Email4 Area4
Table2 - (Bridge Table)
Area
=====
Area1
Area2
Area3
Area4
Table3
AreaID CustName EntityID
======== ======= =======
Area1 Customer1 01
Area2 Customer2 02
Area1 Customer3 01
Area3 Customer3 03
Area4 Customer4 04
Table4
EntityNo EntityName
======= =========
01 EntityA
02 EntityB
03 EntityC
04 EntityD
Scenario -
Table1 and Table3 have many to many relationship on AreaID. We suppose to apply dynamic RLS using UserID column of Table1 which can be filtered through logged in user. To handle many-to-many condition we also have a bridge table with distinct Area so Table1 and Table3 are connected to it with one-to-many.
Applied cross filter on both directions with apply security filter on both sides between Table1 and Table2(BridgeTable). All fine till now, But here the issue when we try to filter Table4 as there is no filter propagation from Table3 to Table4. To make this work we tried to pass filters through writing some logic within DAX.
On the created role for RLS we added a filter for Table4 as below
[EntityNo] IN SELECTCOLUMNS(
FILTER(
'Table3',
RELATED(Table1[UserID])=USERPRINCIPALNAME()
),
"EntityID"
,[EntityID]
)
But we got error as,
The column either doesn't exists or doesn't have relationship with any table available in current context. Issue is known that we are skipping Table2 from the DAX, Not sure how to achieve it. Can someone guide on this?

Related

Radar Chart Comparison - Aggregate Data - PowerBI

I am trying to create a radar chart which allows me to aggregate data and allow me to control the aggregations with slicers. I have the following table with data ready prepared in Power Query with all the unpivoting done. The following table is called Sheet1.
ID
Continent
Country
City
Year
Attribute
Value
1
Europe
Germany
Berlin
2021
F1
50
1
Europe
Germany
Berlin
2021
F2
60
1
Europe
Germany
Berlin
2021
F3
76
1
Europe
Germany
Berlin
2021
F4
80
1
Europe
Germany
Berlin
2021
F5
30
2
Africa
Nigeria
Lagos
2022
F1
23
2
Africa
Nigeria
Lagos
2022
F2
11
2
Africa
Nigeria
Lagos
2022
F3
23
2
Africa
Nigeria
Lagos
2022
F4
23
2
Africa
Nigeria
Lagos
2022
F5
30
2
Africa
Nigeria
Lagos
2022
F6
64
3
Asia
Japan
Tokyo
2021
F1
34
3
Asia
Japan
Tokyo
2021
F3
32
4
Asia
Japan
Tokyo
2021
F1
45
Averaging everything for the year is easy, with an extra table named Year, with one column also named Year and 2 rows, 2021 and 2022. This column goes into a slicer.
Year
2021
2022
The category will be Sheet1[Attribute] and the following measure going to the Y Axis:
_value-slicer_Avg = SWITCH(SELECTEDVALUE('Year'[Year]),
2021,
CALCULATE(AVERAGE(Sheet1[Value]),Sheet1[Year]=2021),
2022,
CALCULATE(AVERAGE(Sheet1[Value]),Sheet1[Year]=2022)
)
This yields the average for a year of choice, when I drop the Year column of the Year table into the slicer
Average
What I want to be able to, is to add another dataset on top of it, which would be easy in case of the data of an ID only (see the Individual Comparison tab of the attached pbix)
Duplicating the table in PowerQuery (no relations needed) as below...
Tables
...I need to create these measures:
_slicer_individual_selection =
SELECTEDVALUE(Sheet1_New[ID])
_value-slicer_individual_selection =
CALCULATE(AVERAGE(Sheet1[Value]),FILTER(Sheet1, Sheet1[ID] = [_slicer_individual_selection]))
And drop the ID of the Sheet1_New table in another slicer.
Individual Comparison
What I want however, is for the second dataset to be the set of the averages of the IDs selected, and the selection should be available at Continent, Country, City or ID level (see the Aggregate Comparison tab of the pbix file attached).
My attempt is not correct, but for the sake of illustration, here it is:
I have replaced the following measure in the Y Axis of the radar chart:
_value-slicer_individual_selection
with this one
_value-slicer_multiple_selection =
CALCULATE(AVERAGE(Sheet1[Value]),FILTER(Sheet1, Sheet1[ID] IN ALLSELECTED(Sheet1_New[ID])))
Failed Attempt of Aggregate Comparison
It also doesn't let me see all the continents, countries, cities or IDs available, I have to keep selecting things to make them show up. I want to be able to show the aggregate set of any selection of IDs based on the supersets available (continent, country, city) as the second set on top of the original aggregate per year. In the above example, I want to see the average for all the data from Tokyo (please note: for 2021 only) as the second set.
Also, I want the 4 slicers on the right-hand side to update, so that I only get to select the ones for 2021 when the selected Year is 2021 and the same for 2022.
Attachments are not supported, please download them from here: https://drive.google.com/drive/folders/1aHS0kFCIUe407bS59VF_MUhrLygc5wfh
To solve your case I'd do following:
Remove YEAR table and substitute values in the slicer With Sheet1[Year]. All other slicer make of Sheet1 columns.
Substitute Sheet1_New with Attributes. Link Attributes[Attribute] to Sheet1[Attribute]. Use Attributes[Attribute] for category in the chart. If you don't want the link then use TREATAS(), but it will slower the measure. The reason for Attributes[Attribute] is that if you use Sheet1[Attribute] as category in the chart, you may filter Attribute values and it will distroy the chart.
Change your _value-slicer_Avg to:
_value-slicer_Avg =
CALCULATE(
AVERAGE(Sheet1[Value])
,ALLEXCEPT(Sheet1,Sheet1[Attribute],Sheet1[Year])
)
All your Other measures do like this:
_value-slicer_individual_selection =
CALCULATE(
AVERAGE(Sheet1[Value])
,ALLEXCEPT(
Sheet1
,Sheet1[Year]
,Sheet1[Attribute]
,Sheet1[ID]
)
)
Make your slicers not influencing Sheet1[Year] slicer and each other except chart. Sheet1[Year] should filter all visuals. Chart should not infuence any sclicer. look at pictures
You can create table with unique values of Attibutes as follows:
Attributes = VALUES(Sheet1[Attribute])
I didn't link it with a Sheet1, so TREATAS was added.
Below the measure which works with multiple selection.
_Avg =
CALCULATE(
AVERAGE(Sheet1[Value])
,TREATAS(Attributes,Sheet1[Attribute])
)
This measure will show average in respect of year only
_value-slicer_Avg =
CALCULATE(
AVERAGE(Sheet1[Value])
,ALLEXCEPT(Sheet1,Sheet1[Year])
,TREATAS(Attributes,Sheet1[Attribute])
)
Regarding slicer look at the picture below:
Try to adjust filtering of slicers and the chart as you need.

Find value in another table - Power BI (DAX)

I'm trying to add a column in Power BI to see if a value appears in another table, without taking the case.
For example from the
Booking Table:
User
Domain
exx
domain1
EPO
domain2
POA
domain3
ER
domain4
and
Log Table:
LogName
Date
RT
12:31
EXX
11:23
POA
9:11
rtt
10:11
I want to see if the User appears in LogName and I'd like to have the output column3:
User
Domain
Column3
exx
domain1
1
EPO
domain2
0
POA
domain3
1
ER
domain4
0
I tried
CALCULATE(COUNT('Booking Table'[User]),
FILTER('Log Table', LOWER('Log Table'[LogName]) = LOWER('Booking Table'[User])
||
LOWER('Log Table'[LogName]) = LOWER('Booking Table'[User])
)
)
but apparently it doesn't work properly.
Thanks in advance for your help!
Measure =
var tbl = SUMMARIZE('Booking Table','Booking Table'[User],'Booking Table'[Domain],'Log Table'[LogName])
var count_user = COUNTX(tbl,'Log Table'[LogName])
return
IF(ISEMPTY(VALUES('Log Table'[LogName])),0,count_user)
Considering the relationship between the two tables is on User & LogName

How to Use NOT IN Query in PowerBI DAX

I have imported Order table from SQL into PowerBI
Order Table has Data Like below.
ID OrderNo CustomerNo OrderDate
1 DC001 1001 2020-06-01
1 DC002 1002 2020-06-09
1 DC003 1003 2020-06-10
Note: I want to Execute below Query in PowerBI DAX
Select Count(Distinct CustomerNo)
From [order] where orderdate >= '2020-06-08' and orderdate <= '2020-06-14'
And CustomerNo
Not in (select CustomerNo from [order] where orderdate < '2020-06-08')
I have tried below code in DAX
MEASURE NOT IN =
VAR indexList =SELECTCOLUMNS (
FILTER('Order','Order'[OrderDate] > [RangeFromDate]),"Distict", DISTINCTCOUNT ('Order'[CustomerNo]))
RETURN
SUMMARIZE (
FILTER('Order',
NOT ('Order'[CustomerNo]) IN indexList),
"Count",Count ( 'Order'[CustomerNo] )
)
Note: [RangeFromDate] is MEASURE dynamically load From date from the slicer.
But Not Working for me.
Kindly Help me to solve this in PowerBI DAX
The EXCEPT function can help with this. It will accept two tables as input, taking the values from the first table, and removing those from the second. I've used a summarize function to ensure each of those tables are distinct (the second table also includes the filter from your SQL subquery). Since they are distinct, I can just COUNTROWS of the resulting table to get the customer count.
RemainingCustomers =
COUNTROWS(
EXCEPT(
SUMMARIZE(Orders, [CustomerNo]),
SUMMARIZE(FILTER(Orders, Orders[OrderDate] < DATEVALUE("2020-06-08")) , [CustomerNo])
)
)

Create difference table depends on slicer or filter

I have two tables Table1, Table2 and two filters Year1, Year2 in Power BI report. I am filtering Table1 depending on Year1, Table2 depending on Year2. I want to create Table3 which shows the difference between Table1 and Table2 after applying filters(Year1 and Year2).
Table1:
Brand Amount Year
ABC 1000 2017
ABC 2000 2018
Table2:
Brand Amount Year
ABC 1000 2017
ABC 2000 2018
Filters contain years. If I select 2017 in Year1 then Table1 will show
ABC 1000 2017
If I select 2018 in Year2 then Table2 will show
ABC 2000 2018
I want Table3 which shows a difference that is
ABC 1000
How can I implement this?
If the data is in two separate underlying tables you should be able to simply use a calculated column:
TableDiff = CALCULATE(SUM(Table1[Amount])-SUM(Table2[Amount]))
If however you are talking about the "Table" visual in Power BI, and you have two table visuals pulling from the same source, I don't believe there is a way to reference the actual data contained in a Power BI visual. You could create a duplicate table in your model and use the above formula, however depending on the size of your data this may not be feasible.

SQL Dev: Updating column from another table's column with where statement

I have the following 2 table examples (large databases with many more columns)
table1
Dirty1 code
Ne yok 553
Bufflo 5767
Ne yok -345
Tchicgo -35
Albunny 543
Dtroit -443
Bufflo -4534
Matatan -45
Ne yok -345
table 2
Dirty2 Standardized
Manhatahn Manhattan
Ne yok New York
Matatan Manhattan
Brocklyn Brooklyn
Albunny Albany
Bufflo Buffalo
Baffalow Buffalo
I want to update table 1 with the standardized city format in table 2 where table1.dirty1 = table2.dirty2 and code is < 0
so the output should look like the following
output table1
Dirty1 code
Ne yok 553
Bufflo 5767
New York -345
Tchicgo -35
Albunny 543
Dtroit -443
Buffalo -4534
Manhattan -45
New York -345
I also want to make sure any that don't have a standardized form in the table 2 get skipped (example: Dtroit and tchicgo)
UPDATE: for Oracle-
UPDATE table1 SET table1.Dirty1= (SELECT table2.Standardized FROM table2
WHERE table1.Dirty1=table2.Dirty2)
WHERE table1.code<0 AND EXISTS (SELECT table2.Standardized FROM table2
WHERE table1.Dirty1=table2.Dirty2);
Note I'm not using Oracle and haven't tested it but it should work.
This should do the trick (MS-SQL)-
UPDATE table1 INNER JOIN table2 ON table1.Dirty1=table2.Dirty2 SET
table1.Dirty1=table2.Standardized WHERE table1.code<0;