I'm setting up a report in PowerBI that will give insight into the amount of work that is planned per department. I know the amount of products to be manufactured for specific projects and the time this takes per department in minutes. I've created a measure to calculate the total amount of time planned per department for a specific period, but it is giving an unexpected total that I don't understand.
The datamodel consists of four tables: a table that contains unique product ids,
a table that contains information on running projects (including the amount of products to be manufactured by a specific date), a table that contains the manufacturing routing which shows how much time is required to manufacture a specific product per department, a calendar table that contains all dates for the next 10 years
Relationships between the tables currently all have a cross filter in both directions. The image below contains the model and also the example data I've used:
Model
What we’re trying to do is create an overview of the amount of work planned per department in hours. So for this I’ve created a measure:
Total time in hours = (SUM(Projects[Amount]) * SUM(Routing[Time (in minutes)]) / 60
When I used this measure for a specific product, everything seems to be fine. However, when looking at the total time per departement I get a higher value. I'm not sure where this comes from. The table in the image shows the numbers I see in PowerBI. The total for Total time in hours (227) is much higher then the sum of the total time for the individual products:
Total time
Can anyone help me figure out how PowerBi calculates this total of 227?
There is no link between 'Projects' and 'Routing'[Department]. So at your grand total level, SUM ( 'Projects'[Amount] ) => (5 + 5 + 5 + 5 + 4 + 4) => 28 and SUM ( 'Routing'[Time (in minutes)] => (186 + 301) => 487. Thus, your total is (28 * 487) / 60 => 13,636 / 60 ~=> 227.
Ultimately, the behavior is "correct" in that the DAX you've written is evaluating conforming to spec, but you'll likely need to take a different approach to the calculation.
One possible approach is:
New Total time in hours =
SUMX ( // SUMX iterates a table, and performs a calculation per row, collecting these
// subtotals in a sum.
VALUES ( 'Products'[Product ID] ), // VALUES gives us a table made up of unique values
// in context from the named column (or table).
[Total time in hours] // your already existing measure
)
Related
I am having a big problem, I have a table that has counts of employees the clocked in a a specific time rounded off to 15 minute increments each day. Included in the table are the end times. I am trying to create a bar graph which shows the 15 minutes time windows along the X axis and the Y axis should show the total number of people on the clock at that time however all I can get it to show is how many people "clocked in" at each of those spans. I'm not sure what I am doing wrong. I made a separate time table in 15 minute increments and related it to the employee table and still, same result. ANy help would be greatly appreciated!!!
I am using a simple measure to get the sum. SUMEMPCNT=SUM('data'{EMPCNT])
Here is a sample of the data table:
Here is a sample of the current chart.
You can use the build in Quick Measure "Runnung total" to get your DAX formula:
It will give you this measure:
Number running total in TimeStamp =
CALCULATE(
SUM('Table'[Number]),
FILTER(
ALLSELECTED('Table'[TimeStamp]),
ISONORAFTER('Table'[TimeStamp], MAX('Table'[TimeStamp]), DESC)
)
)
that you can visualize in a clustered column chart:
We run a hotel business. The structure of my fact table is arranged as a P&L report. Every month has a row for specific line items.
There's Month/QTD/YTD/L12M period slicers.
I've added columns for the total number of rooms sold and travelers per month in order to use them as references for writing Measures. This number stays constant throughout the month.
I want to build unit analytics into the dashboard. For example, the cost of linens per traveler per month. If I choose QTD, I want to add up the linen cost this quarter and divide by # of travelers this quarter.
To do this, I first created a Travelers Measure to start. The issue I'm running into is how to make it react to the period slicers.
If I try to use:
Travelers = SUM it adds up all the travelers or rooms sold even if it's within the same month (ie. in January - if I have 10 line items for the report and there were 10 total travelers, then it would show 100 travelers)
Travelers = MIN displays the correct number based on the selected month slicer, but fails to SUM the travelers based on the period slicer chosen. (eg. if I had 30 travelers QTD, it would still only show the number from the chosen month).
I'm no longer sure whether this is a DAX issue or if I should arrange my data differently.
Thank you!
Link: https://www.dropbox.com/s/5wl4dc5f560cswv/TestReport.pbix?dl=0
I have a database that has some values as "Date", "StopedTime", "PlannedProductionQtt" and "PlannedProductionTime". These values are sorted by equipment, as the little example below.
What I need to do is divide PlannedProductionQtt by PlannedProductionTime and then multiply by StoppedTime. After this, I want to make a graph that shows it day by day.
At first I thought it was easy, made a new measure PlannedProductionQtt/PlannedProductionTime = SUM(PlannedProductionQtt)/SUM(PlannedProductionTime) (assume it worked without the table name).
And then I did another measure Impact = SUM(StoppedTime)*PlannedProductionQtt/PlannedProductionTime.
When I plotted a clustered column chart with this measure in values and a the day for the axis, at first I thought I had nailed it, but no. The BI summed all of PlannedProductionQtt and divided by the sum of all PlannedProductionTime for the day, and multiplied by the sum of the StoppedTime of that day.
Unfortunately, this gives me wrong results. So, what I need is a measure (or some measures) that would make it equipment by equipment and the sum it by day.
I don't want to make new tables or columns for theses calculations because I actually have 32 items of equipment, 3+ years of data, more than 1 classification of StoppedTime and the databases for PlannedProduction use more than one line per day per equipment.
To make it clear I added one column as Impact to show the difference.
So, if I sum the column Impact per day, I would have for day 1,2 and 3 the results 110725, 61273 and 220833.
However, if I sum first all the PlannedProductionQtt for day 1, divide it by the sum of PlannedProductionTime of day 1 and multiply it by the sum of StoppedTime of day 1 (which is how PowerBi is calculating) I will have 146497.
I inserted the difference in the table below to make the differences clear:
As Jon suggested in a comment, here is what solved my needs:
measure_name = SUMX( source_table , DIVIDE ( source_table[PlannedProductionQtt] , source_table[PlannedProductionTime] , 0 ) ) * SUM( source_table[StoppedTime] )
You have two different types of data you want to divide there, time and int, so you would probably need to unify that. Easiest way to do it would be from the Transform data panel, selecting the column and changing its
format
The division is done fairly easily, can you try creating a new measure as follows
measure_name = CALCULATE(
DIVIDE(<source_table>[PlannedProductionQtt],
<source_table>[PlannedProductionTime],
0)
* <source_table>[StoppedTime]
)
Then it's only a matter of using it as values in a graph and the 'Date' column in x axis.
I need to find one way or another the following formula in Power BI:
Total Hours of Use of a Machine = Hours Function * Range of Functioning
where Hours Function is the hours of use of a certain machine. Take it at a cost that for each machine is a constant and Range of Functioning is the difference between the final date of the evaluation and the initial date, measured in hours.
For example, I want to measure the Total Hour Use of a Machine in between 15/10/2019 and 14/20/2019. So the math is the following:
Assume: 2 machines
Hours Function machine A: 6
Hours Function machine B: 9
Range of Functioning = 15/10/2019 - 14/10/2019 = 24 hours
The output:
Total Hours of Use of a Machine A: 144
Total Hours of Use of a Machine B: 216
I need to do that in Power BI in a way that any user moving a slicer of date, refresh the Total Hours of Use of a Machine.
I don't find any way that I can get the difference between the final date of the evaluation and the initial date and put in DAX or a new column.
You have to use measures if you want to recalculate the value when you change the date with a slicer.
The first step is to be sure to be able to calculate the number of day selected by your slicer.
It seems to be easy but if you use the function FirstDate on your calendar table directly integrated in PowerBI.
You'll never have what you expect.
The tricks here to get this number of day is to calculate the number of rows in your calendar table with the function countrows.
When you have this number day you just have to multiply this by 24 ( hours) and by the sum of your "Hours Function machine".( 6 for A 9 for B in your example )
( It's important to use the sum or another aggregate function like average because if you have multiple value the measure fall in error because it need only one value to multiply).
The dax formula looks like :
= COUNTROWS(('Calendar')) * Sum(Machine[Hours function])
You can then display this measure filtered by the Machine Name and a date slicer(based on your calendar table).
I want to create a table about leave and need a cummulative total.
The Annual Leave Column2 DAX is
Annual Leave Column2 =
CALCULATE (
SUM (Sheet1[Debit/Credit]),
ALL ( Sheet1 ),
FILTER(Sheet1, SUM(Sheet1[Debit/Credit])>20), Sheet1[Date] <= EARLIER ( Sheet1[Date] )
)
and for the column 3 is
column 3 = IF( Sheet1[Annual Leave Column2]>20, 20, Sheet1[Annual Leave Column2] )
But the result when it already 20 and there is a -1 in next date it will still count 20 and stuck in 20.
And the result that I need is:
I just think, Can we stop the calculation if the value already 20? and continue the calculation if met -1. Or there is another way how to do it?
It's looks like if I using IF it's just make the visualization into 20 but not set the data into 20, that's why it's stuck in 20 because all the sum is more than 20.
Your best bet is for your source system to either not allow annual credits that exceed the annual cap, or to provide you with the capped annual leave amount directly (rather than trying to calculate it in Power BI).
Even if the source system doesn't store the capped annual leave amount, it may be easier to calculate it in a query using SQL than using Power BI. (I'd recommend a separate question for this.)
Why Do I Say This?
In Excel, a running (or cumulative) total is calculated row-by-row based on the value from the previous row. This makes it easy to "override" the running total and have that override apply to each subsequent row. E.g. you can cap the running total at 20, and the cell underneath acts as if the running total is 20. The cells underneath the cap have no idea that the running total is not really 20.
In DAX, the running total is calculated independently on each row (meaning each row looks at all the rows prior to the current rows date and calculates what the actual running total is). This makes it impossible to override the running total (e.g. by capping it at 20) and have that adjusted running total feed into the next row. The next row always knows what the real running total is.
There's no way to tell DAX to look at the previously calculated running total and add to it because a column cannot reference itself (as user5226582 mentioned, it's a circular dependency). DAX, unlike Excel, runs calculations column by column rather than cell by cell, so it can't use the output of a column as an input for the same column.
Dirty & Incomplete Workaround
A dirty workaround would depend on how many times Annual Credits can get disregarded. Each time all or part of an annual credit is disregarded, it adjusts the running total for all subsequent cells.
For example, on 1-May-17, the true running total is 20.5, but you throw away the 0.5. This means all future rows are based on a running total of 20 on 1-May-17, not 20.5.
You could certainly create a calculated column that identifies the first time the running total is capped (1-May-2017). You would then calculate an Adjusted Running Total that uses the previously calculated running total prior to 1-May-17, but after 1-May-17 ignores the prior running total and instead sums the [Debit/Credit] column from 1-May-17 only plus 20. (Adding 20 because we know the running total is at 20 on 1-May-17 and that won't be reflected in the sum of the [Debit/Credit] column.)
Running Total Is Capped = IF([Annual Leave Column2] > 20, 1, 0)
Running Count of Capped =
CALCULATE (
SUM ( Sheet1[Running Total Is Capped] ),
ALL ( Sheet1 ),
FILTER ( Sheet1, Sheet1[Date] <= EARLIER ( Sheet1[Date] ) )
)
Adjusted Running Total =
IF (
[Running Count of Capped] = 0,
[Annual Leave Column2],
20
+ CALCULATE (
SUM ( Sheet1[Debit/Credit] ),
ALL ( Sheet1 ),
FILTER (
Sheet1,
Sheet1[Date] <= EARLIER ( Sheet1[Date] )
&& Sheet1[Running Count of Capped] > 1
)
)
)
This solution doesn't hold up though because it only works for the first time the cap is hit. Each time you hit the cap, you'll need to adjust the running total in the same way, with a new set of calculated columns that adjusts the adjusted running total. If you can hit the cap 20 times, or 50 times, you'll need the above set of calculated columns repeated 20 or 50 times too.
You can't adjust for the cap across all rows simultaneously, because the first adjustment affects when the next adjustment happens. In your example data, the true running total on 5-Aug-17 is 21, meaning we'd want to reduce it to 20. However, because we've gone over the cap 3 times before, we've already shaved 3.5 days from the running total as a result, and so the adjusted running total is 17.5 and therefore doesn't need capping.
Apart from the sheer number of calculated columns you'd need, the model would also not hold up well to increased volume of data. The EARLIER function is iterative, meaning it runs its calculation once for every row. The more rows, the longer it takes. Using the EARLIER function over & over again as this quick & dirty workaround does would be a performance killer. I strongly recommend finding another solution, ideally before the data reaches Power BI.
Sidenote: If you're going to use the EARLIER function, I'd recommend indexing each row so they're guaranteed to have a unique number rather than relying on the date field as an index. Using the date field as an index could cause unexpected results if you have multiple credits/debits on the same date.