I'm new to DAX.
I'm currently using Power BI and trying to create a total sum of sales that use a few different SKUs (or IDs)
I can use this to filter down to 1 sku ("A1"):
Measure = CALCULATE([Sum of Sales],Table4[SKU]="A1")
but I would like to filter down to five different SKUs.
Example Data:
2 1,050.54
3 43,925.20
4 8,596.00
5 1,630.00
8 3,330.00
A1 45.24
A2 499.87
A3 53,567.05
A4 337.92
A5 4,265.00
AB 12,651.94
ACC 7,634.95
ADV -1,769.95
ANT 1.60
AUTO 9,655.40
BOOT 268.00
Is this possible?
CALCULATE is defined as CALCULATE(<expression>,<filter1>,<filter2>…) This means that you can use multiple filters at one time. However, the multiple filters will act at the same time. Meaning that the data would have to meet both conditions.
So doing BadSumOfSales:=CALCULATE([Sum of Sales],Table3[SKU]="A1",Table4[SKU]="AB") will not give you what you need. Since the SKU would have to be equal to A1 and AB, it will return blank
Since you have five items you would like to included in your filtering, you should leverage the SWITCH function. This will allow you to accommodate multiple conditions that should return TRUE and then let you return FALSE for anything else
TotalsSumOfSales:=CALCULATE([Sum Of Sales],
SWITCH(Table4[SKU],
"A1",TRUE(),
"A2",TRUE(),
"A3",TRUE(),
"4" ,TRUE(),
"5" ,TRUE(),
"8" ,TRUE(),
FALSE()
))
Another way to get around this would be using the OR function. This is a great option, but only really works well when you have two filters at a time. If you have more than two, you will have to do some nesting that can get complex. So for your case I would stick with the SWITCH, but here is an example of how it would look:
OrTotalSumOfSales:=CALCULATE([Sum of Sales],
OR(
Table4[SKU]="A1",
Table4[SKU]="A2"
))
The best idea in this case is to use IN Operator in DAX. The Performance is way better than pipe operator or OR and the code becomes more readable.
This is only supported in the latest versions of DAX.
GroupingSales:=CALCULATE([Sum of Sales],Table[SKU] IN {"A1","A2","A3","AB"})
You can also use CONTAINSROW.
More info: https://www.sqlbi.com/articles/the-in-operator-in-dax/
Just a third way alternative to the Or version.
You can use the double pipes '||' which acts as an Or statement in the filter.
Measure = CALCULATE([Sum of Sales],Table4[SKU]="A1" || Table4[SKU]="A2" ||
Table4[SKU]="A3" ||Table4[SKU]="A4" || Table4[SKU]="A5")
Well I think based on your request to filter down to 5 different SKUs that you actually shouldn't be using DAX to solve your problem.
If you just insert a pivot table in Excel you can add SKU to rows and sales to values. If you need, you can adjust the aggregate (but I think it defaults to SUM) so you should already have the right data. Only thing remaining is to filter it down to just the SKUs you want. You can do the same in Power View just by creating a table. Then you can add SKU to the filter pane and select the 5 skus you want.
Appreciate your using Power BI,
-Lukasz
http://dev.powerbi.com
http://blogs.msdn.com/powerbidev
Make a feature request: https://support.powerbi.com/forums/265200-power-bi
Sign up for Power BI: http://www.powerbi.com
Related
See this data set below. It has 3 columns (PTQ, % Growth, $ Growth) that all need ranked individually then summed up and then ranked again for a total power rank of each region. Is there any way I can do this with a single formula? I do this a lot and it would be nice not to have to rank everything individually each time. Basically I need to end up at the "Power Rank" column.
To clarify, I do not want to rank first on one column then another, they all need to be ranked equally together.
Thought I'd add a solution for non-365 users:
Edit: slight amendment so that the returned ranking mimics that of the RANK function, with thanks to #Scott Craner
=MMULT(N(MMULT(CHOOSE({1,2,3},RANK(A2:A10,A2:A10),RANK(B2:B10,B2:B10),RANK(C2:C10,C2:C10)),{1;1;1})>TRANSPOSE(MMULT(CHOOSE({1,2,3},RANK(A2:A10,A2:A10),RANK(B2:B10,B2:B10),RANK(C2:C10,C2:C10)),{1;1;1}))),ROW(A2:A10)^0)+1
which may require committing with CTRL+SHIFT+ENTER, depending on the version of Excel being used.
The static
{1;1;1}
relates to the fact that 3 columns are being queried, and could of course be replaced with a dynamic alternative.
We can use Office 365 LET and SORT. RANK does not allow the use of arrays, so we need to improvise with MATCH and SORT.
=LET(
ptq,A2:A10,
grwt,B2:B10,
grwthd,C2:C10,
ptqrnk,RANK(ptq,ptq),
gwtprnk,RANK(grwt,grwt),
gwtdrnk,RANK(grwthd,grwthd),
sm,ptqrnk+gwtprnk+gwtdrnk,
MATCH(sm,SORT(sm),0))
I'm trying to get the sum of Sales with uniuqe Catatery i'm using DAX Formula below
Countoracle = CALCULATE(SUM('Data Source'[Sales) ,DISTINCTCOUNT ('Data Source'[ItemAr]))
getting error
The True/False expression does not specify a column. Each True/False expressions used as a table filter expression must refer to exactly one column.
You are looking at it the wrong way.
Rather than cramming it into one measure try breaking them into 2 parts.
And please elaborate your question. What is your goal here ?
Software: MS Excel 2016
Here is a table
Given, there will alway be same number of triggers for a particular ID. But I don't want to count those triggers multiple times.
I tried the following DAX. My expected answer is 72, but I get 143 instead. How to fix?
Distinct_Matches:=CALCULATE(sum(Incidents[Triggers]),DISTINCT(Incidents[Incident_ID]))
Use this:
=SUMPRODUCT(B2:B7/COUNTIF(A2:A7,A2:A7))
Here is the formula with structured references:
=SUMPRODUCT(Incidents[Triggers]/COUNTIFS(Incidents[Incident_ID],Incidents[Incident_ID]))
The below would work, assuming that Incident_ID's trigger value is the same across the ID Number.
Measure 1:=SUMX( DISTINCT(Table1[Incident_ID]), CALCULATE(AVERAGE(Table1[Triggers])))
Table1 just being the name I used as part of the quick test.
The idea being that the sumx would iterate though every unique Incident_ID and sum the result of the calculate statement. The calculate statement is using average, since it will return the unique value. E.g. Average(41+41) = 41. You could also use MIN or MAX as well.
I have 3 tables, 1 of which I want to fill in columns with data based on the other 2. Tables are roughly structured as follows:
Table 1 (Semi-Static Data)
SubGroup Group
----------- -----------
subgroup(1) group(a)
subgroup(2) group(b)
subgroup(3) group(b)
subgroup(4) group(c)
etc.
Table 2 (Variable Data)
SubGroup DataValue
----------- -----------
subgroup(1) datavalue(i)
subgroup(2) datavalue(ii)
subgroup(3) datavalue(iii)
subgroup(4) datavalue(iv)
etc.
Table 3 (Results)
Group TotalValue
----------- -----------
group(a) totalvalue(m)
group(b) totalvalue(n)
group(c) totalvalue(o)
etc.
Where the TotalValue is the sum of all DataValue's for all subgroups that belong to that particular Group.
e.g. for group(b) ---> totalvalue(n) = datavalue(ii) + datavalue(iii)
I am looking to achieve this calculation without adding any additional columns to the Data tables nor using VBA.
Basically I need to perform a COUNTIFS where there is an additional VLOOKUP matching the subgroup criteria range to the group it belongs to, and then only summing for datavalue's that match the group being evaluated. I have tried using array formulas but I'm having issues making it work. Any assistance would be very appreciated. Thank you,
EDIT: Wanted to add some details surrounding my question. First all Google searches did not provide a suitable answer. All the links had solutions to a slightly different problem were the VLOOKUP term is not dependent on the SUMIFS criteria but rather another single static variable. Stack Overflow offered similar solutions. Please let me know if anymore details are required to make my post suitable for this forum. Thank you again.
You can use the SUMPRODUCT function to do it all at once. The first reference $B$2:$B$5 is for the Group names, the second reference $E$2:$E$5 is for the datavalues. The G2 reference is for the group names in the third table, you can enter this formula for the first reference and then drag and fill for the rest.
=SUMPRODUCT($E$2:$E$5 * (G2 = $B$2:$B$5))
Some cell references, and sample data, would be helpful but something like this might be what you want:
=SUMIF(C:C,"="&INDEX(A:A,MATCH(E5,B:B,0)),D:D)
WADR & IMHO, this is simply bad worksheet design. For lack of a single cross-reference column in Table2, any solution would have to be a VBA User Defined Formula or an overly complicated array formula (the latter of which I am not even sure is possible). The data tables are not normalized database tables you can INNER JOIN or GROUP BY ... HAVING.
The formula you are trying to achieve is akin to,
=SUMPRODUCT(SUMIF(D:D, {"subgroup(2)","subgroup(3)"}, E:E))
That only works with hard-coded values as arrayed constants (e.g. {"subgroup(2)","subgroup(3)"}). I know of no way to spit a dynamic list back into the formula using additional native Excel functions but VBA offers some possibilities.
HOWEVER,
The simple addition of one more column to Table2 with a very basic VLOOKUP reduces all of your problems to a SUMIF.
The formula in the new column D, row 2 is,
=VLOOKUP(E2, A:B, 2, FALSE)
The formula in I2 is,
=SUMIF(D:D, H2,F:F )
Fill each down as necessary. Sorry if that is not what you wanted to hear.
Thank you everyone that responded and reviewed this post. I have managed to resolve this using an array formula and some matrix algebra. Please note that I am not using VLOOKUP (this operator cannot be performed on arrays) nor SUMIFS as my title states.
My final formula looks like this:
{=SUM(IF([Table2.xlsx]Sheet1!SubGroup=TRANSPOSE(IF([Table1.xlsx]Sheet1!Group=G2,[Table1.xlsx]Sheet1!SubGroup,"")),[Table2.xlsx]Sheet1!DataValue))}
Very simply, I create an array variable that compares the Group being evaluated (e.g. cell G2) with the Groups column for Table 1 and outputs the corresponding matching SubGroups. This results in an array with as many rows as Table 1 had (N) and 1 column: Nx1. I then transpose that array (1xN) and compare it to the SubGroups column (Mx1, M being the number of rows in Table 2) and output the DataValues column for the rows that have a corresponding SubGroup (MxN). Then I perform a sum of the whole array to return a single value.
Notice that as I didn't include a value_if_false output return on either IF operators, it will just populate with FALSE in the arrays were the conditions are not met. This does not matter though for the final result. In the first IF, FALSE will not match the SubGroups so will be ignored. For the second all values FALSE passed to SUM will be calculated as 0. The more complicated question is that it grows the amount of memory required to process as we are not filtering to just have the values we want.
For this application I decided against filtering the subarray as the trade-off in resource utilization was acceptable. If the data sets were any bigger though, I would definitely try doing it. Another concern was that I did not understand fully the filtering logic that I was using based on http://exceltactics.com/make-filtered-list-sub-arrays-excel-using-small/ so decided to simplify. Will revisit this concept latter as I think it will work. I might have completed this solution but was missing transposing the array to compare properly so abandoned this route.
I have a large data set with 4 columns of interest all containing text, namely pokemon moves. The columns "move 1" through to "Move 4" each contain a different move, and each row differs in the combination.
eg.
" A | B | C | D | E".
" 1 Pokemon | Move 1 | Move 2 | Move 3 | Move 4".
" 2 Igglybuff | Tackle | Tailwhip | Sing | Attract".
" 3 Wooper | Growl | Tackle | Rain Dance| Dig".
~ 1000 more
My issue is this:
I wish to filter this data set for rows (pokemon) containing a certain combination of moves from a list.
eg. I want to find which pokemon have both "Growl" and "Tackle". These moves can appear in any of Moves 1 to 4 (aka order of the moves is unimportant)
How would I go about filtering for such a result. I have similar situations in which I would want to search for a combination of 3 or 4 moves, the specific order of which is not important, or also search for specific pokemon possessing a specific combination of moves.
I've attempted to use functions such as COUNTIF without avail.
Help / Ideas are much appreciated
There are a number of options for advanced filtering in excel that you might consider:
Option 1 - Advanced Filters
Advanced filters give you the power to query over multiple criteria (which is what you need). You can also easily do it as many times as you want to generate the final datasets using each filter. Here is a link to the advanced filter section for Microsoft Excel 2010, which is virtually identical here to 2007. It would be a great place to start if you want to move outside of just using basic formulas.
If you do go down this route, then follow the directions on the site in terms of steps:
Insert the various criteria that you have selected in the top rows in your spreadsheet and specify those rows in the list range
Set the criteria range to the place holding all your data on a single worksheet
Run the filter and look at the resulting data. You can easily do a count on the number of records in that reduced data set.
Option 2 - Pivot Tables
Another option that you might look at here would be to use Pivot tables. Pivot tables and pivot charts are just phenomenal tools that I use in the workplace every day to accomplish exactly what you are looking for.
Option 3 - Using Visual Basic
As a third option, you could try using visual basic code to write a solution. This would give you perfect control as you could specify exactly the ranges to look at for each of the conditions. Unfortunately, you would need to understand VB code in order to use this solution. There are some excellent online resources available that can help with this.
=COUNT(INDEX(MATCH(B2:E2, MoveList, 0), 0)) > 0
will return TRUE if any of the values in the range B2:E2 (Moves 1 through 4) are in the range defined by Move List. You want to use a named range so that you can easily copy this formula down for all of your thousand rows.
If you remove the last part that checks whether the COUNT() value is greater than zero, you get:
=COUNT(INDEX(MATCH(B2:E2, MoveList, 0), 0))
which will return the number of moves that the Pokemon has that match a move on the move list.
MATCH() takes three arguments: a lookup value, the lookup range, and the match type. I don't fully understand why, but wrapping that part of the formula in INDEX() seems to let you use an array for the first argument. Maybe someone here can provide a better explanation.
In any case, the formulae above do appear to solve the problem.
Finally, if you're only checking for a few moves, instead of using a confusing formula and a named range as above, you could just make a column for each move that you want to check for, e.g. "Has Growl?" and "Has Tackle?". You would then just use =COUNTIF(B2:E2, "Tackle") and =COUNTIF(B2:E2, "Growl"). You could then make another column that sums these columns and filter out the zero values to display only Pokemon who have Tackle or Growl.
I looked at these two pages when researching how to accomplish this:
https://www.excelforum.com/excel-general/786407-find-if-any-value-on-one-list-exists-on-another.html
https://www.deskbright.com/excel/using-index-match/