Remove duplicates from OLAP Drill in SSAS - action

I am using Visual Studios BIDS to modify an existing OLAP cube.
In SSMS: There is an underlying fact table (FactTableMain) with a very fine grain that contains 10 different measures to track the status of an application (they act almost like a flag). The measures either have the individual's ID value or are NULL.
In SSAS Visual Studio OLAP:
There are 10 measure groups. Each measure group is based on a DSV named query that selects 1 of the FactTableMain measures where MeasureName IS NOT NULL.
A drill action for each measure group with only the PersonName and PersonID columns being returned.
The drills for each measure group:
shows duplicates (as not all fact table columns are return columns for the drill)
Do not return the expected number of rows that the measure count displays
I have tried:
multiple MDX conditions using filter and distinct on the drill through action, but they either make no difference or the action disappears entirely
Create a junk drill dimension that selects the distinct IDs from the FactTableMain and set that as the only return column for the drill through action (made no difference to drill through return rows)
Creating New (Standard) Action as a rowset and dataset, using MDX action expressions
I think I need a New (Standard) Action with an MDX Action expression with these properties:
Target type = Cells
Target object = All cells
Actions Content Type = Rowset
My current MDX query does return results, but only for the first measure's overall total and it is not formatted correctly at all. It does not work if I select a different measure in the client application, rerun the query, and drill again. I have searched and searched, but I am out of ideas and sitting in a black pit of doom. :(
My current MDX query is:
WITH
SET [person] AS
NonEmpty([person].[person].[person])
MEMBER CurrentMeasure AS
[Measures].CurrentMember
SELECT
NonEmpty
(
Filter
(
[Quarter].[Quarter].[Quarter].MEMBERS
,[Quarter].[Quarter].CurrentMember
)
) ON COLUMNS
,(
[person]
,NonEmpty([person].[person ID].[ID])
) ON ROWS
FROM [Applications];
Goal:
I would ultimately like the drill action to be dynamic enough to know the current measure the user is selecting and filtered by the user's dimension selection for rows/columns.
Questions:
Is there a way to filter distinct or non empty rows using a condition for the original drill through action? I know there are drill limitations, but is there something that would workaround the drill's limitations?
How can I create a Standard Rowset action that is dynamically to the user's selections (my goal).
Any ideas?
A URL action type is not an option for our business needs.
EDIT: I removed everything unnecessary from the DSV and am selecting only distinct rows. Each ID can have more than 1 application and an application can have more than 1 area of interest. Now the drills return 1 row per ID, application, and area of interest. We only want the drill to return the distinct IDs, no matter the number of applications or areas of interest. I am not sure where to go from here. Can I filter our the application number and/or areas of interest dimensions in the drill?

I believe that you are going too fast too quick.
The DSV should show the data without duplication in the browser. If it's not, go back to the DSV and check what it is. Maybe create a view (an Indexed view) on top of the fact table, so you can make sure that you query only the data that you want. Also: are you sure that your dimensions are linked correctly? Sometimes duplication appears due to dimensions not being set up correctly with wrong keys for linkage.
In MDX:
If you create a Calculation in the Calculation tab you can do drill in it. Otherwise, you'll have to write the correct MDX query each and every time.
HTH.

See the very last example at:
http://asstoredprocedures.codeplex.com/wikipage?title=Drillthrough&referringTitle=Home
You have to deploy that ASSP assembly to SSAS. It is used to pickup the current context on all attributes during execution of the action. But it will return totals by employee for whatever measure the user launched the action from.
"select {[Measures].CurrentMember} on 0, NON EMPTY [person].[person].[person].Members on 1 from (select (" + ASSP.CurrentCellAttributes([Measures].CurrentMember) + ") on 0 from [Application])"

Related

In Power BI Desktop, how can I group all measures together (instead of placing under different tables)?

Tableau automatically groups measures together but Power BI Desktop doesn't natively support this. I find it annoying to have to place measures under imported tables as the measures don't really belong to those "parent tables" (and quite often take input from multiple tables — which one would you consider the "parent"?)
So I experimented with some workarounds and I'm sharing the successful (as of the date of this post) ones here:
Method 1 (recommended): "Model" view > "Enter data" to enter a manual data table. Give a name like "_Measures_" so it appears on top of tables, and keep only the default dummy column "Column". Create/move measures under it, then right click to delete that "Column". Now you're left with a blank table that groups those measures under it.
Method 2: "Data" view > "New table" to create a DAX calculated table. Rest the same as above, except that for a DAX calculated table you can't delete the dummy column but instead you can hide it.
You can also "Enter data" using Power Query Editor but I don't recommend going with that extra step -- workarounds are supposed to be quick (and dirty) anyways!
Final results look like this (note the difference of the icons):

In Power BI, how can I create a column that changes based on a slicer and visualization?

I'm pretty new to Power BI. I'm unsure how to approach this.
I have one visualization that displays the ten most frequently bought products in a time frame that is set by a slicer. In another visualization, I display how those products have been selling over the past few years (this time frame is not determined by the slicer). I want to display only the ten products that come from the first visualization, not the ten most common over the time frame in the second visualization.
How can I accomplish this? The approach I have in mind (and I'm open to others) is to create a true/false column that changes with the first visualization. "True" would be for products that are frequently bought as determined by the first visualization in the slicer-determined time range, and the second visualization would only look at values with a "true" in that column. How can I create a column (or table, maybe?) that changes depending on a visualization?
Clarification: most of the pages will say Top10 ... Actually, the measure used was a simple Top5 that includes products with the same number of orders than the 5th product. Therefore, to avoid dealing with larger images, 7 products will be seen but it is a Top5 ranking. The idea is you can replace it with your custom TopN measure.
What I understood:
The simplification of your model plus the disconnected help table would be:
I have one visualization that displays the ten most frequently bought
products in a time frame that is set by a slicer.
The Date slicer belongs to the Dates table in the Data model.
The table viz represents the number of rows in the sales table in the
current context (for each product within the Date range).
The table viz is sorted according to the [#Rows] measure in descending
order.
The table viz only presents the TopN products even without the presence
of the [#Rows] measure due to the presence of the [TopOrders]
measure within Filters on this visual. [TopOrders] is 1.
On the second page you create:
A slicer with the Dates[Date] column (the same one used on the
previous page).
A matrix with Products[ProductName] on the rows, HDates[Year] on
the columns, and a measure on values.
From the View tab, you select the Sync Slicers option.
Inside the Sync Slicers pane:
In the Sync column, check the boxes related to the necessary pages.
In the Display column uncheck the box that contains the over
years report.
So far all we have done is pass the time frame context from page 1 to page 2.
Since the TopN context depends on the time frame context, we can now use the [TopOrders] measure as a Filters on this visual in the matrix. Again, [TopOrders] is 1.
Why do the numbers differ between rows and not between columns?
Also, in this example, the Sales table only has information up to 12/31/2020 but the visualization shows an additional year and the Sales[Amount] values for each order is $1 so that [#Orders] and [SalesAmount] are the same for easy comparison.
HDates is not related to the model and for each combination of HDates[Year]-Products[ProductName], the [SalesAmount] measure is using the information coming from the previously hidden slicer and the respective Products[ProductName] because the information coming from HDates[Year] has no effect yet.
In order to complete this exercise, it only remains to modify the [SalesAmount] measure in such a way that it removes the filter on the time frame (Dates[Date]) and it recognizes HDates[Year] as Dates[Year].
SalesAmount :=
CALCULATE(
SUM(Sales[Amount]),
ALL(Dates),
TREATAS(VALUES(HDates[Year]),Dates[Year])
)
And this is the final result.
I hope it works for someone or the idea can be improved.

How can I have dynamic axis which is responsive on slicer value, without using bridge table, use just DAX

Hi everyone, I have a chart which I need that the x value (Axis) changes by changing the slicer value (this slicer is the yellow one that has all the Dims (x values)) and it comes from DimList table. For example, at the moment the chart is totalfreight by custid, but I need if I check the empid from the yellow slicer the chart value changed to totalfreight by empid. This happens for all of the slicer values.
But I don't like bridge table or any method that has a bad effect on performance because the FactTable has a billion rows and I modeled it in SSAS, tabular model and has a live connection. Thanks in advance.
I assume you're referring to the approach that uses a bridge table described in this article. I agree that you may face some performance problems given the amount of data in your model.
First of all, you should try to see if there's some other Power BI frontend functionality that you can use directly in the report, without changing your data model. Perhaps you can use Power BI bookmarks, links or maybe a custom visual?
If not, there's another approach you can use in the data model, that does not rely on bridge tables. Disclaimer: I haven't tested this - there could be other performance issues involved.
Construct a new dimension table with all the members from your individual dimensions. Ie. create a union of all EmpIDs, CustIDs, etc. Make sure you indicate the type of ID in a separate column. The table should look like this:
DimensionId MemberId
categoryid 1
categoryid 2
categoryid 3
custid 1
custid 2
custid 3
...
Let's name this table 'All Dimensions'. The table should not have any relationships to other tables (this is similar to the Parameter Table pattern.
Change your measures to apply a virtual relationship whenever something is selected on the 'All Dimensions' table, to properly filter the fact table:
SUM('factSale'[Freight])
would become:
SWITCH(
SELECTEDVALUE('All Dimensions'[DimensionId]),
"categoryid", CALCULATE(SUM('factSale'[Freight]),
KEEPFILTERS(TREATAS(VALUES('All Dimensions'[MemberId]), 'factSale'[CategoryId])),
"custid", CALCULATE(SUM('factSale'[Freight]),
KEEPFILTERS(TREATAS(VALUES('All Dimensions'[MemberId]), 'factSale'[CustId])),
"empid", CALCULATE(SUM('factSale'[Freight]),
KEEPFILTERS(TREATAS(VALUES('All Dimensions'[MemberId]), 'factSale'[EmpId])),
// ... etc. for all dimensions ...
, // Fallback, when nothing is selected on 'All Dimensions'
IF(NOT ISFILTERED('All Dimensions'[MemberId]),
SUM('factSale'[Freight])
)
)
Put the [DimensionId] column into a slicer and use the [MemberId] column as the axis on your bar chart. Note that the chart will not show anything unless exactly one item has been filtered on the [DimensionId] slicer.
Explanation: The SWITCH statement determines if any selection has been made on the [DimensionId] column of the 'All Dimensions' table. In that case, a filter is applied to the fact table, depending on which dimension has been selected, using the TREATAS function. We're using KEEPFILTERS to make sure that any existing filters made directly on the individual dimensions are kept as-is.
In case no selection has been made on the [DimensionId] column, we want to fall back to the standard measure SUM('factSale'[Freight]) but since we don't want to repeat this measure for all items on the [MemberId] column, we use IF(NOT ISFILTERED( ... to make sure that we return only a blank value, if [MemberId] is currently used on the chart axis.

DAX Joint value

I am trying to create a measure in DAX to find the joint value (sum) of a fact table by filtering two dimension tables to have the same column value.
Here's an image of the relationship
Each Department in Users are linked to table Registret. They are giving resources to projects. The table Projects are Taking Resourcs. What I am trying to accomplish is a measure that can find the amount a department uses of it's own resources. So I figure if I can filter Registret[Users] and Registre[Project] where Users[Department] = Projects[Department] I would get the value.
I'd like to use the Projects[Department] as a basis. So that table below would show the amount of internal department registration by each Department in Projects.
Department(Projects) InternalRegistration
A Value
B Value
So far I've been trying with something like
CALCULATE(Registret[Registret]; FILTER(Users; Users[Department] IN ALLSELECTED(Projects[Departments])))
But this will only show the correct value if I in a slicer single out a Department from table Projects. Is it possible the solution is some Joint table between Users and Projects?
Edit:
The top table shows the matrix of joint values in Registret between Users and Projects.
Edit2:
Image of my table data.
Notice that the filter arrows only point downward. This means that selecting Projects[Departments] isn't going to filter Users[Departments] since there is no filter path connecting them. You are also missing the SUM function in your measure.
Try tweaking your measure to the following:
= CALCULATE(SUM(Registret[Registret]);
FILTER(Users; Users[Department] = SELECTEDVALUE(Projects[Departments])))
If you're working in a matrix or a table, the SELECTEDVALUE should pick up the row/column filter context from the visual, whereas ALLSELECTED only picks up filter context from slicers or report/page/visual level filters.
You can also use ...IN VALUES(... instead of ...= SELECTEDVALUE(....
= CALCULATE(SUM(Registret[Registret]),
FILTER(Users, Users[Department] IN VALUES(Projects[Department])))
Both of these should produce the following:

Power bi box and whisker: filter with an if statement

MWE set up:
1) From the Power Bi visual website: https://app.powerbi.com/visuals/ there is a custom download "Box and Whisker (Jan Pieter)"
2) Download sample.
3) create new measure with dax formula:
Distinct count score = if(distinctCOUNT(Courses[Score]) > 4, average(Courses[Score]), Blank())
4) Add a Stacked column chart with Course as the axis and the newly created 'Distinct count score' as the Value and get the following:
5) compare this graph to the Box and Whisker provided by Power BI:
Here is my problem. I only want to show values in the Box and Whisker where the Distinct Count of Scores is greater than 4 -- So I only want Physics to show up (like the stacked column chart above).
So if I try the solution working with the stacked bar chart using the Dax formula. I get the following--nothing shows up:
And this is what I want to happen:
Question:
Is there a way in Power BI run and distinct count statement within a Box and Whisker chart to only show data with > 4 distinct values (or any if statement)?
I want it to be formula based, I cannot just 'visual filter' items I do not want.
Possible answer:
I thought about going to the source code to try and 'throw in' a if statement. But I went to the developers git hub: https://github.com/liprec -- I couldn't find the repo for this visual.
Basically this is due to the way the box and whisker chart is working. The visuals needs a dataset to calculate the values (mean, median, etc.) and use those values to show the box and whisker.
So in your case you need to create a measure that is on the same level as the scores (because those values are needed) and is only available. See the screenshot for a visual explanation of the needed measure.
I created the measure with the follow DAX measure:
Filter Score = IF(CALCULATE(DISTINCTCOUNT(Courses[Score]), ALLEXCEPT(Courses, Courses[Course]))>4, MIN(Courses[Score]), BLANK())
The Boolean expression of the IF statement calculates the distinct scores per course via a CALCULATE expression and the ALLEXCEPT filter option to ignore everything but the course value. And the TRUE part returns the score which needs to be aggregated, so the MIN and the FALSE part return a BLANK() value so is can be ignored.
When you add the new measure and create a BW chart it will only show 'Physics' course results.
If you need more help, please let me know here or via email.
-JP
BTW: I just updated my PowerBI visual GitHub repository (https://github.com/liprec/PowerBI-custom-visuals) and added my box and whisker chart and my hierarchy slicer to it in the folder oldAPI.
The crux of your problem, as far as I can tell, is that you want to filter visuals to courses that have a particular number of distinct values. Which visual you want to use is almost irrelevant (though it was helpful to have a sample Power BI workbook to follow along with).
The way I'd approach this (and not saying this is the best or only way)
Step 1
Create a new Course dimension table, with one row for each unique course. In the sample workbook, you can click 'Enter Data' and manually type in the data.
Course
------
English
Math
Physics
Step 2
Next, create a calculated column in the new table and calculate the distinct count for each course. This isn't a measure - it's a column in your table, that uses the Distinct Count calculation from your question.
Distinct Count = CALCULATE(DISTINCTCOUNT(Courses[Score]), SUMMARIZE('Courses','Courses'[Course]))
The SUMMARIZE works like a GROUP BY. In essence, creating one row per course with a distinct count of scores.
Step 3
Use this new attribute as a filter on your visual. You can then dynamically alter the number of distinct values as you feel like (4, 3, 2).
I know this isn't quite as good as typing a formula into the visual filter field, though in practice it's still formula driven. The formula is just on an underlying table.
Why so complex?
The reason you have to do this for the Box & Whiskers visual, whereas your 'Distinct Count score' measure works so well, is that on the column chart, you are displaying a single value (the average score). The Box & Whiskers chart, by contrast, is plotting every individual score.
In fact, if you removed the 'Course' from the axis of your column chart, the value changes as it adds back in the courses you filtered out. (The reason for this is that, if no course is on your axis, your formula calculates the distinct count of all the courses, which is 7). Likewise, if you were to filter your column chart to a particular session, your column chart would go blank (since in any given session, no course has more than 4 distinct values).
The technique I've described above fixes those problems, because it filters out the courses Math & English from the get-go. It doesn't matter if you've filtered to a single session, or not filtered by course at all. English & Math will always be excluded as long as their distinct count is below the value you specify.
Hope this helps.