ssas tabular model use roles so customer can only see suppliers used - ssas-tabular

I have a ssas tabular model that has dimCustomrer, dimSupplier and a fact table.
I created a role for customers so they can only see themselves and this works perfectly fine.
Is it possible for the role to filter the Dimsupplier table so they can only see the suppliers they have used?
Searching google I can't find anything that seems to help.

Do you want to filter dimSupplier based on the fact table? Yes, that is possible by enabling bi-directional filtering on the relationship between dimSupplier and the fact table, and also setting the security filtering behaviour to "both directions":
However, bi-directional filtering can have some performance impact if your model contains large amounts of data.
Alternatively, you could import an aggregated version of the fact table, that only contains all the distinct combinations of customers and suppliers (2 columns). Call this table BridgeCustomerSupplier, or something like that. Then, you add a row-level filter to your role on the dimSupplier table, and use LOOKUPVALUE, to see if there's a matching record in BridgeCustomerSupplier, for the current supplier (in dimSupplier - the row context), and the current customer.

Related

Ignoring space characters when linking tables

I’m experiancing a problem when trying to link to tables in the database expert. The two fields that link the tables have exactly the same information except one table always has an additional space. For example;
Table 1 = Multivitamin/Tablets
Table 2 = Multivitamin//Tablets
‘/‘ are representing spaces
Formulas won’t help (e.g. extractstring etc) as it’s the tables themselves I need to link together
This is preventing me from retrieving the information I need. Any advice on how I can get around this?
There are some ways to come across this:
Consider using a command as datasource instead of tables. When writing the query of the command you can define the join condition yourself.
If you have access to the data source, you could add a calculated field to the tables to contain the normalized field values and then use these for linking in CR.
Alternatively, one could create views in the database, either adding normalized "linking fields" or providing the joined tables results.
If it's only a few rows in CR, you could consider using SQL fields or subreports to retrieve data from Table 2.

Feedback about my database design (multi tenancy)

The idea of the SaaS tool is to have dynamic tables with dynamic custom fields and values of different types, we were thinking to use "force.com/salesforce.com" example but is seems to be too complicated to maintain moving forward, also making some reports to create with a huge abstraction level, so we came up with simple idea but we have to be sure that this is kinda good approach.
This is the architecture we have today (in few steps).
Each tenant has it own separate database on the cluster (Postgres 12).
TABLE table, used to keep all of those tables as reference, this entity has ManyToOne relation to META table and OneToMany relation with DATA table.
META table is used for metadata configuration, has OneToMany relation with FIELDS (which has name of the fields as well as the type of field e.g. TEXT/INTEGER/BOOLEAN/DATETIME etc. and attribute value - as string, only as reference).
DATA table has ManyToOne relation to TABLES and 50 character varying columns with names like: attribute1...50 which are NULL-able.
Example flow today:
When user wants to open a TABLE DATA e.g. "CARS", we load the META table with all the FIELDS (to get fields for this query). User specified that he want to query against: Brand, Class, Year, Price columns.
We are checking by the logic, the reference for Brand, Class, Year and Price in META>FIELDS table, so we know that Brand = attribute2, Class = attribute 5, Year = attribute6 and Price = attribute7.
We parse his request into a query e.g.: SELECT [attr...2,5,6,7] FROM DATA and then show the results to user, if user decide to do some filters on it, based on this data e.g. Year > 2017 AND Class = 'A' we use CAST() functionality of SQL for example SELECT CAST(attribute6 AS int) AND attribute5 FROM DATA WHERE CAST(attribute6 AS int) > 2017 AND attribute5 = 'A';, so then we can actually support most principles of SQL.
However moving forward we are scared a bit:
Manage such a environment for more tenants while we are going to have more tables (e.g. 50 per customer, with roughly 1-5 mil per TABLE (5mil is maximum which we allow, for bigger data we have BigQuery) which is giving us 50-250 mil rows in single table DATA_X) which might affect performance of the queries, especially when we gave possibilities to manage simple WHERE statements (less,equal,null etc.) using some abstraction language e.g. GET CARS [BRAND,CLASS,PRICE...] FILTER [EQ(CLASS,A),MT(YEAR,2017)] developed to be similar to JQL (Jira Query Language).
Transactions lock, as we allow to batch upload CSV into the DATA_X so once they want to load e.g. 1GB of the data, it kinda locks the table for other systems to access the DATA table.
Keeping multiple NULL columns which can affect space a bit (for now we are not that scared as while TABLE creation, customer can decide how many columns he wants, so based on that we are assigning this TABLE to one of hardcoded entities DATA_5, DATA_10, DATA_15, DATA_20, DATA_30, DATA_50, where numbers corresponds to limitations of the attribute columns, and those entities are different, we also support migration option if they decide to switch from 5 to 10 attributes etc.
We are on super early stage, so we can/should make those before we scale, as we knew that this is most likely not the best approach, but we kept it to run the project for small customers which for now is working just fine.
We were thinking also about JSONB objects but that is not the option, as we want to keep it simple for getting the data.
What do you think about this solution (fyi DATA has PRIMARY key out of 2 tables - (ID,TABLEID) and built in column CreatedAt which is used form most of the queries, so there will be maximum 3 indexes)?
If it seem bad, what would you recommend as the alternative to this solution based on the details which I shared (basically schema-less RDBMS)?
IMHO, I anticipate issues when you wanted to join tables and also using cast etc.
We had followed the approach below that will be of help to you
We have a table called as Cars and also have a couple of tables like CarsMeta, CarsExtension columns. The underlying Cars table will have all the common fields for a ll tenant's. Also, we will have the CarsMeta table point out what are the types of columns that you can have for extending the Cars entity. In the CarsExtension table, you will have columns like StringCol1...5, IntCol1....5, LongCol1...10
In this way, you can easily filter for data also like,
If you have a filter on the base table, perform the search, if results are found, match the ids to the CarsExtension table to get the list of exentended rows for this entity
In case the filter is on the extended fields, do a search on the extension table and match with that of the base entity ids.
As we will have the extension table organized like below
id - UniqueId
entityid - uniqueid (points to the primary key of the entity)
StringCol1 - string,
...
IntCol1 - int,
...
In this case, it will be easy to do a join for entity and then get the data along with the extension fields.
In case you are having the table metadata and data being inferred from separate tables, it will be a difficult task to maintain this over long period of time and also huge volume of data.
HTH

DAX SUMMARIZE function isn't respecting row-based security in my Power BI Model

I'm adding Row-level security to a Power BI model and it's working on all the normal tables, but there's a DAX table created from a SUMMARIZE that's ignoring the security. I've created a small model that reproduces the issue - am I doing something wrong here, or is this behavior intentional?
Here's my data model - "Raw Table" is just a manual table with some numbers in it and a filter column:
"DAX Table" is created with a SUMMARIZE statement that just makes it a copy of the manual table (since every row is unique anyways):
DAX Table = SUMMARIZE('Raw Table', 'Raw Table'[Number], 'Raw Table'[Filter])
Here's what the content of the tables look like when nothing is filtered:
I've added row-level security that filters the Filter table to just the "Show" records:
And through the join, this appears to filter the Raw table normally - when it's enabled, I can only see the rows with "Show" in them (as expected). However, the DAX table continues to show everything, even the filtered rows that I'm not supposed to see:
What am I doing wrong here? Since I'm not allowed (via RLS) to see the rows labelled "Hide" in the raw table, shouldn't those also be excluded from the SUMMARIZE statement? I realize that adding a slicer on the Filter table and slicing the Raw table doesn't impact the SUMMARIZE statement (I still see all the rows in that case) - am I just seeing the same thing here? Since I'm prevented from seeing these rows based on a security setting, I'd expect them to be hidden from my DAX as well.
Assuming I'm doing this correctly and this is intentional, how can I create a DAX table that does respect my security filters (as I need to do this in my full model)?
Here's a link to the testing PBIX file as well.
Calculated Tables (and columns) get calculated when the model is loaded, and materialized. Not at runtime.
You will need to connect that table to your model so security propagates there aswell.

Report filter on 1-to-many joined tables

I have a report that shows maintenance information for medical instruments. The selection criteria are based on several tables and fields. I needed to change the criteria, but results were not as expected. I managed to find the cause, but do not know what to do to get to the wanted situation.
So basically the problem is as follows:
I have 2 tables that are linked:
* Equipment (information related to a specific instrument eg EqmId)
* ObjectFeature (information related to a specific feature eg ObjfEqmId, ObjfId, ObjfYesno)
An equipment can have 0, 1 or many ObjectFeatures, and the tables are linked via
Equipment.EqmId -> ObjectFeature.ObjfEqmId with a left-outer join.
The problem I have is that i want to filter out al EqmId's where (ObjfId="64" and ObjfYesno=1). I do not want to see these EqmId's in the final list.
In my current setup, I have only removed the ObjfId="64" lines, but since an EqmId can have multiple features, it still is present in the list...
In my original report Equipment is my main table, so I need a way to filter this table before I do further filtering and joining.
I find myself limited in the selection formula, and thought of using a SQL command on the database. But I can't get my head around how to do this.
How and where should I do the filtering?

FileMaker Pro 12 Auto-populating Tables

I'm new to Filemaker and need some advice on auto-populating tables.
Part 1:
I have TableA which includes many records with client information. I want a separate TableB which is identical to TableA except that it is "de-identified"; that is, it does not contain two of the fields, first name and last name.
I would like the two tables to interact such that if I add a new record to TableA, that same record (sans first and last name) appear automatically in TableB.
Part 2:
In addition to the above functionality, I would also like said functionality to be dependent on a specific field type from TableA. For example, I enter a new record, which has a "status" field set to "active," into tableA. I then want that record to be auto-popualted into TableB; however, if I add another record with a "status" of "inactive," I want that that record auto-populated into a TableC but not into TableB.
FileMaker can perform this with script triggers so long as every layout where TableA will be edited has a layout script trigger of OnRecordCommit connected to it. When the record is committed (which can happen in a number of ways), the attached script will run, which you can use to create the appropriate record in the appropriate table.
The script could create the record in a number of ways. If the primary keys for both records are the same, you could use lookups. You could export the record in TableA and then import it into the correct table. You could pass the field information as a parameter to the script. The best choice really depends on your needs.
Having said that, I would question the wisdom of this approach. It brings up a few questions that would seem to complicate matters. For example, what happens when the status changes? When a record in TableA is deleted? When fields in TableA are modified? Each of these contingencies (and others) will require thought and more complicated scripts.
So I would ask what problem you're really trying to solve. My best guess is that you are trying to keep the name information private from certain users. User accounts and privileges with dedicated layouts for each privilege can solve this without the need for duplicate tables. FileMaker privilege sets can be quite granular.
For example, you can specify that users with PrivilegeA can create records and view names, but PrivilegeB users can only view records if the status is "active" and the name fields are not available to them, while PrivilegeC users can view records if the status is "inactive" and the name fields are also not available to them.
I would definitely use filters and permissions on the "status field" to achieve this and not two mirroring tables. Unless the inactive information is drastically different, you would be complicated your solution and creating more possible pitfalls.