Forum Discussion
Filter values from one table in another without relationship DAX
- 2 years ago
Hi talespin Please see the solution below. As you mentioned earlier creating a measure using the formula wasn't the right way and creating a role and applying RLS was the right approach. Since no one was able to provide a RLS DAX query for this requirement we have itself come up with a DAX solution to achieve the requirement. Please see below.
1.) All semi-colon values in DIM_ACT columns must be replaced by "|" symbol for this formula to work. Either change the source data or create a calculated column to replace ";" with "|".
2.) Eliminated DIM_USER table and brought in EMAIL ID column to DIM_ACT table itself.
3.) There is only 1 record for a single user in DIM_ACT under a single GROUP.
4.) Create a ROLE in Manage roles and apply below DAX under FACT_ACTUALS table. Using the below DAX , when the user logs in he will be able to see only the values separated using "|" in the respective columns of DIM_ACT and when ALL is present in any of the columns, he will be able to see all the values available in FACT ACTUALS./* FILTER DIM_ACT TO FETCH THE RECORD HAVING ONLY THE LOGGED IN USER EMAIL ID & VALUES ASSIGNED UNDER LEVEL COLUMN */
&& [LEVEL]
IN(
VAR _LEV =
MAXX (
FILTER
( 'DIM_ACT',
[EMAIL ID] = USERPRINCIPALNAME () ),
'DIM_ACT'[_LEV]
)/* TAKE THE PATH LENGTH OF LEVEL COLUMN. THIS IS DONE BECAUSE THERE COULD BE N NUMBER OF VALUES SEPARATED BY | SYMBOL IN DIM_ACT TABLE
AND WE NEED TO SEPARATE THEM AS INDIVIDUAL VALUES */VAR _LEVLEN = PATHLENGTH (_LEV )
/* CREATE A VIRTUAL TABLE WITH COLUMN NAME LEVLIST HAVING THE LIST OF LEVEL COLUMN VALUES */
VAR _LEVTABLE = ADDCOLUMNS ( GENERATESERIES ( 1, _LEVLEN ), "LEVLIST", PATHITEM ( _LEV, [Value] ) )
/* SELECT THE COLUMN VALUES AND PASS THE VALUES TO LIST */
VAR _LEV_list = SELECTCOLUMNS ( _LEVTABLE, "LEVEL", [LEVLIST] )
/* ADD ALL THE LEVEL VALUES FROM FACT_ACTUALS. THIS IS FOR A USER WHO HAS VALUE "ALL" ASSIGNED TO HIM UNDER LEVEL IN DIM_ACT TABLE */
VAR _ALLFACTLEV = ADDCOLUMNS ( VALUES ( FACT_ACTUALS[LEVEL] ), "ALL", "ALL" )
/* RETURN ONLY THE VALUES ASSIGNED IN LEVEL COLUMN IN DIM_ACT FROM FACT TABLE FOR LOGGED IN USER OR RETURN ALL THE VALUES FROM FACT TABLE WHEN THE LEVEL COLUMN IS PROVIDED AS ALL */
RETURN
SELECTCOLUMNS
(
FILTER ( _ALLFACTLEV, [LEVEL] IN _LEV_LIST || [ALL] IN _LEV_LIST ),
[LEVEL]
)
)
&& [LABEL]
IN (
VAR _LAB =
MAXX (
FILTER ( 'DIM_ACT', [EMAIL ID] = USERPRINCIPALNAME () ),
'DIM_ACT'[LABEL]
)
VAR _LABLEN = PATHLENGTH ( _LAB )
VAR _LABTABLE =
ADDCOLUMNS ( GENERATESERIES ( 1, _LABLEN ), "LABLIST", PATHITEM ( _LAB, [Value] ) )
VAR _LAB_LIST =
SELECTCOLUMNS ( _LABTABLE, "LABEL", [LABLIST] )
VAR _ALLFACTLAB =
ADDCOLUMNS ( VALUES ( FACT_ACTUALS[LABEL] ), "ALL", "ALL" )
RETURN
SELECTCOLUMNS (
FILTER ( _ALLFACTLAB, [LABEL] IN _LAB_LIST || [ALL] IN _LAB_LIST ),
[LABEL]
)
)&& [SOURCE] IN ------ Similarly repeat the above code for other columns in DIM_ACT
talespin Please ignore the slicers I have placed in the report. I have just placed it for reference in future. These are my queries 1.) How to pass all these column values ([LEVEL] & [LABEL] & [SOURCE] & [CC] & [ORG] from DIM_ACT individually using DAX and match respective columns in FACT_ACTUALS table ? Values in columns of DIM_ACT are separated by semicolon and I need to match one by one in respective columns in FACT_ACTUALS because FACT_ACTUALS will only have individual values under LEVEL and not values separated by semi-colon.
2.) FACT table does not have values as ALL hence I would like to filter those columns having value as ALL meaning it should display all the available values under this column (no filter should be applied to this column). Eg: for user SDK@abc,com, he should see all the LEVEL = 100 & A20 & K40 and labels should only be those values under LEVEL and not all the values from FACT_ACTUALS. There will be only a single Table visualization displaying all the columns in FACT_ACTUALS. When user logins he should see only those values assigned in DIM_ACT and not all the values under LEVEL & other columns mentioned. Hope using [LABEL] & [LEVEL] & [SOURCE] & [CC] & [ORG] & [LOC] will accomplish this but not for ALL values. Please let me know for any clarification. TIA.
- varung88992 years ago
Helper II
Thanks a ton talespin This solution works perfectly. Only thing is that I am unable to test this as a role or another user when trying via Power BI Web. My intention is exactly to provide access via the table itself going forward and not add users manually in RLS however as part of data testing I am unable to do so by defining this measure under FACT_ACTUALS table in Manage Roles section. Its giving me error in my visual while viewing as a Test role. Do you have any thoughts pls ?
- talespin2 years ago
Solution Sage
hi varung8899
A word of Caution, what you are doing in not RLS. If you want to restrict access to data, use RLS rather than relying on a measure to filter your data.
You need to change your Datamodel, Role should directly filter Users.
- varung88992 years ago
Helper II
Thanks for your valuable guidance talespin . May I pls have a final ask to close this thread. If I have a column called GROUP in DIM_ACT having different group names for each user & multiple users can be tagged to the same group in future, could you please let me know what will be your approach to tweak the above measure and create a role in RLS ? Appreciate your perseverance. TIA.