I have a problem where I need to figure out if a project has values outside it's start and finish date range.
Below is a simple relationship of dimension table containing start and finish dates of the projects. And a fact table containing time registration.
The table below has a column 'Outside Date Range' Which I'd like to have a true/false value. for example if Main2 Table contains a date Monday, May 13, 2018. The column should show false.
I tried something like
Outside Date Range = CALCULATE(SUM(Main2[Value]), FILTER(Main2, Main2[Time] < LOOKUPVALUE(Main[Start], Main[Project], ALL(Main2[Project]))))
But not really sure how to approach the relationship between the two tables properly.
The two approaches I would suggest are either a calculated column or a measure.
Calculated column:
Outside Date Range =
VAR rowsOutsideRange =
CALCULATE (
COUNTROWS ( Main2 ),
FILTER (
RELATEDTABLE ( Main2 ),
Main2[Time] < Main[Start]
|| Main2[Time] > Main[Finish]
)
)
RETURN
IF ( rowsOutsideRange > 0, TRUE (), FALSE () )
You were pretty close in your solution! Since you have a relationship between the two tables RELATEDTABLE will only return the related rows which removes the necessity of a LOOKUPVALUE(). Also, counting the rows is sufficient since we only want to know if any rows exist outside of the range, not how many.
You could also create a measure:
Outside Date Range Measure :=
VAR rowsOutsideRange =
CALCULATE (
COUNTROWS ( Main2 ),
FILTER (
Main2,
Main2[Time] < MIN ( Main[Start] )
|| Main2[Time] > MAX ( Main[Finish] )
)
)
RETURN
IF ( rowsOutsideRange > 0, TRUE (), FALSE () )
Which is pretty similar to the calculated column, the only this is we need to aggregate the start and finish dates. On its own this measure doesn't have any value, it needs to be sliced by a project to be correct. If you would really want to you could use a SUMX() type of construction to create an overall TRUE/FALSE statement which tells you if any of the project have rows outside their ranges but for your use case I don't see the benefit of that.
The choice between a calculated column and a measure is dependent on the legibility of the code and resource usage. A calculated measure uses more memory and a measure uses more CPU.
Looking at your case I would go for a calculated column, which seems the most simple and clear solution.
Hope that helps!
Jan
Related
I am putting together a measure of the difference between two datetime values and have ran into negative durations due to bad data, that I need to omit from the calculation.
My DAX function is as follows:
Job_length =
SUMX (
jobs ,
DATEDIFF (
jobs[actualstart] ,
jobs[actualend] ,
MINUTE
)
)
This returns the following output:
How can I change the formula to skip rows where the iterator expression returns a negative value?
The question is a bit lacklustre in the sense that it is perhaps the wrong question that is being asked! E.g. why is there data where actualstart < actualend to begin with? This is something you should fix in ETL prior to loading data into Power BI.
Or better yet, ensure that this is not allowed within your source systems. Perhaps there is a bad setting somewhere in your stack that results in this behavior in the data.
However, to do exactly as you describe you can apply a filter to the table you are iterating over within the SUMX function to remove rows that don't comply with the requirement. I have here assumed that only rows where actualend is strictly greater than actualstart are evaluated:
Job_length =
SUMX(
FILTER (
jobs ,
[actualstart] < [actualend]
),
DATEDIFF (
jobs[actualstart],
jobs[actualend],
MINUTE
)
)
I think I have just been staring at this for too long and have worked myself into a corner.
So let's say I have the following data:
I have locations that get monthly utility usage numbers. I want to create a clustered bar chart that shows how many months have data.
The "Merge_Use" column can have numbers, blanks, and N/A. Any number > 0 OR N/A is considered complete. 0 or blank is incomplete.
I want a clustered bar chart that shows % complete, and is split by quarter and metric type, that shows the global total % complete, but can be filtered to show the % complete by region or individual location (relationships for TRT_ID to region is housed in a separate table). For some reason I can't wrap my mind around the measure that would do that.
This was my first try. I used a calculated column, but it wasn't until after I got to the visual stage that I realized that my calculated column is static and won't be affected by filtering. (It sounds silly now but I made a column that assigned each completed field a % out of the total fields, i.e. 1/total # rows, thinking I could just sum these together in the visual).
How would you do this?
I may have solved my own problem.
I added a conditional column with Yes/No for "completed" based off my criteria. (i.e. if "" then "No", else "Yes")
Then added the following measure:
% YES =
DIVIDE (
CALCULATE ( COUNT ( Leadership_Usage_Tracking_v2[Completed] ), Leadership_Usage_Tracking_v2[Completed] = "YES" ),
CALCULATE ( COUNT ( Leadership_Usage_Tracking_v2[Completed] ), ALLSELECTED ( Leadership_Usage_Tracking_v2[Completed] ) )
)
Seems to be working so far!
My data
Fact
iddimUser iddimtime
123 81200
124 84500
DimTime
iddimtime FullTime
81200 08:12:00.0000000
84500 08:45:00.0000000
Desired Table calculation
iddimUser iddimtime Time
123 81200 08:12:00.0000000
124 84500 08:45:00.0000000
I require to bring to the fact table a specific time from the time dimension base on one of the multiple relationships I have (I have several IdTimes in the fact table).
I tried this column calculation but getting an "A table of multiple values was supplied where a single value was expected" error
FullTime = TIME(
HOUR(CALCULATE( VALUES(DimTime[FullTime] ),
USERELATIONSHIP ( Fact[iddimtime], DimTime[iddimtime]))),
MINUTE(CALCULATE( VALUES(DimTime[FullTime] ),
USERELATIONSHIP ( Fact[iddimtime], DimTime[iddimtime]))),
SECOND(CALCULATE( VALUES(DimTime[FullTime] ),
USERELATIONSHIP ( Fact[IniciaProce], DimTime[iddimtime]))))
FullTime1 =
FORMAT(RELATED(DimTime[FullTime]),"hh:nn:ss")
This you can use as alternative to your measure and it will be much faster.
FullTime2 =
FORMAT(
LOOKUPVALUE(
DimTime[FullTime]
,DimTime[iddimtime]
,[iddimtime]
)
,"hh:nn:ss"
)
Why do you use the userelationship if there is only one active relationship between fact and dim tables ? All you need is the related function to access the related row in the dim table:
Note:
Ensure that The [iddimtime] column is the one who creates the relationship between both tables.
Related() is an iterator. Never use it with a calculate involving USERELATIONSHIP() in a calculated field.
RELATED() is used to access the column values from many side to one-side. Conversely, RELATEDTABLE() is used to access columns from one side to many side.
Please test this, and let me know if It solves your problem.
FullTime =
TIME ( HOUR ( RELATED ( DimTime[FullTime] ) ), MINUTE ( RELATED ( DimTime[FullTime] ) ), SECOND ( RELATED ( DimTime[FullTime] ) ) )
I have a column for which I need to count how many times the value "Good" is present without calculating the "Neutral" Value?
This is the sample table:
Col1
Bad
Neutral
Good
Bad
Neutral
Okay
Here is what I have so far but I kept
Measure = CALCULATE(Col1],Table[Col1] = "Good",ALLEXCEPT(Table,Table[Col1]="Neutral" ))
but I end up getting this error:
A single value for column 'Intune Owner Email' in table 'users' cannot be determined. This can happen when a measure formula refers to a column that contains many values without specifying an aggregation such as min, max, count, or sum to get a single result.
How can I work around this?
Why whould you need to except Col1 = Neutral for this?
This measure counts the number of rows where Col1 = "Good":
# Good :=
CALCULATE (
COUNT ( 'Table'[Col1] ) ,
'Table'[Col1] = "Good"
)
If you are after a different type of filtering semantics, you can try also invoking KEEPFILTERS:
# Good Variant =
CALCULATE (
COUNT ( 'Table'[Col1] ) ,
KEEPFILTERS ( 'Table'[Col1] = "Good" )
)
The difference between the semantics can be shown here:
I know this must be extremely simple, but every example I can find online only works within a single table. I've simplified my situation to these two tables:
I want to add a calculated column to the first table, showing the most recent value for that id. It also needs to work with text.
There are a variety of ways to do this kind of thing as I've explained before and all of the solutions there can be adjusted to work in this case.
Doing this as a calculated column and with a second table, you need to make sure you are using row context and filter context appropriately.
Here's are a couple different possibilities I think may work:
MostRecentValue =
MAXX ( TOPN ( 1, RELATEDTABLE ( Table2 ), Table2[date] ), Table2[value] )
In this one, RELATEDTABLE is doing the work of filtering Table2 to only the rows where id matches Table1.
MostRecentValue =
VAR PrevDate = CALCULATE ( MAX ( Table2[date] ) )
RETURN CALCULATE ( MAX ( Table2[value] ), Table2[date] = PrevDate )
The relationship is more subtle here. Wrapping the MAX in CALCULATE forces a context transition so that the row context (which includes id) is applied to Table2 as filter context.