Join us for an expert-led overview of the tools and concepts you'll need to pass exam PL-300. The first session starts on June 11th. See you there!
Get registeredPower BI is turning 10! Let’s celebrate together with dataviz contests, interactive sessions, and giveaways. Register now.
Dear all,
this might not be the best task for PowerBI but we have made so much great reports in our organization and would prevent to have this report in another tool.
We want to identify in our hour bookings overlapping entries and I have really no idea how to do that 🤣🙈
Any help is highly appreciated.
We have a table with time entries:
employee | date | start_hour | start_minute | end_hour | end_minute | KST | Task |
100005 | 01.03.2021 | 6 | 55 | 16 | 30 | 37001 | 10430 |
100005 | 01.03.2021 | 16 | 30 | 17 | 30 | 9 | 10430 |
100005 | 02.03.2021 | 6 | 55 | 18 | 30 | 37001 | 10430 |
100005 | 02.03.2021 | 17 | 30 | 18 | 0 | 9 | 10430 |
100005 | 03.03.2021 | 6 | 55 | 16 | 25 | 37001 | 10430 |
100005 | 03.03.2021 | 16 | 25 | 17 | 25 | 9 | 10430 |
I want to identfy the blue marked lines, cause start hour+min of the second red line is overlapping with the end hour+min (red).
Any idea how to solve this?
thanks in advance
regards
Sebastian
Solved! Go to Solution.
If you wish to use Direct Query, you can (NB, I've added another overlapping row to date 2/03/2021 to check if all overlapping rows are returned) :
1) Create the DateTime columns in the table using calculated columns with:
StartTime = TableDQ[date] & " " & TableDQ[start_hour] & ":" & TableDQ[start_minute]
And the equivalent for the EndTime column. Set the Data type to Date/time:
2) Create a measure to establish the row order by date/employee/task:
Sum StartTime = SUM(TableDQ[StartTime])
Order by date =
RANKX (
FILTER (
ALLEXCEPT ( TableDQ, TableDQ[employee], TableDQ[date], TableDQ[Task] ),
NOT ( ISBLANK ( [Sum StartTime] ) )
),
[Sum StartTime],
,
ASC
)
This gives you the following table visual:
3) Next create measures to establish the StartDateTime and EndDateTime for the comparison:
StartDateTime =
VAR starttime =
MAX ( TableDQ[StartTime] )
RETURN
CALCULATE (
starttime,
ALLEXCEPT ( 'TableDQ', 'TableDQ'[date], 'TableDQ'[employee], 'TableDQ'[Task] )
)
EndDateTime =
VAR PrevPeriod = [Order by date] - 1
RETURN
CALCULATE (
MAX ( TableDQ[EndTime] ),
FILTER (
ALLEXCEPT ( TableDQ, 'TableDQ'[date], 'TableDQ'[employee], TableDQ[Task] ),
[Order by date] = PrevPeriod
)
)
4) and finally the measure to identify the rows which overlap:
Indentify overlapping DQ =
VAR SelPeriod =
CALCULATE (
[Order by date],
FILTER ( TableDQ, NOT ( ISBLANK ( [EndDateTime] ) ) )
)
VAR _table =
CALCULATETABLE (
VALUES ( TableDQ[date] ),
FILTER (
TableDQ,
[Order by date] >= SelPeriod - 1
&& [Order by date] <= SelPeriod
)
)
VAR _date =
CALCULATETABLE (
VALUES ( 'TableDQ'[date] ),
FILTER ( ALL ( TableDQ ), [StartDateTime] < [EndDateTime] )
)
RETURN
COUNTROWS ( INTERSECT ( _table, _date ) )
And you will get this:
Proud to be a Super User!
Paul on Linkedin.
Hello,
I used your code with some modifications based on my specifications and keep coming up with the same error, even though I am in import mode.
My data table is structured like this. I created the StartTime and EndTime as a column rather than a measure..
Here is my modified code.
2)
##
Sum StartTime = SUM(Timecard_Dimensions[StartTime])
##
##
I changed the allExcept to All as I have a lot of dimensions in the table that are not in the visual, which is possible a issue.
3)
##
StartDateTime =
VAR starttime =
MAX ( Timecard_dimensions[StartTime] )
RETURN
CALCULATE (
starttime,
ALL(Timecard_Dimensions[Clock_In_Time], Timecard_Dimensions[Clock_In_Time], Timecard_Dimensions[timecard_id], Timecard_Dimensions[timecard_Fact.Date_of_Work])
)
##
##
EndDateTime =
VAR PrevPeriod = [Order by date] - 1
RETURN
CALCULATE (
MAX ( Timecard_Dimensions[Clock_Out_Time] ),
FILTER (
ALL(Timecard_Dimensions[Clock_In_Time], Timecard_Dimensions[Clock_Out_Time], Timecard_Dimensions[timecard_id], Timecard_Dimensions[timecard_Fact.Date_of_Work]),
[Order by date] = PrevPeriod
)
)
##
4)
##
Indentify overlapping Measure =
VAR SelPeriod =
CALCULATE (
[Order by date],
FILTER ( Timecard_Dimensions, NOT ( ISBLANK ( [Clock_Out_Time] ) ) )
)
VAR _table =
CALCULATETABLE (
VALUES ( Timecard_Dimensions[Timecard_Fact.Date_of_Work] ),
FILTER (
Timecard_Dimensions,
[Order by date] >= SelPeriod - 1
&& [Order by date] <= SelPeriod
)
)
VAR _date =
CALCULATETABLE (
VALUES ( 'Timecard_Dimensions'[Timecard_Fact.Date_of_Work] ),
FILTER ( ALL ( timecard_Dimensions ), [Clock_In_Time] <= [Clock_Out_Time] )
)
RETURN
COUNTROWS ( INTERSECT ( _table, _date ) )
##
I have tried any all of these to the visuals going down through the steps. Order by Date works in the visual without the error as well as StartDateTime. EndDateTime runs the error as well as Indentify overlapping measure.
If anyone has any tips on how to solve this problem, that would be greatly appreciated. Thank you in advance.
Hi @SebastianAlmer ,
I've switched to import for testing:
@jaideepnema
I have an index that I can use. But it's not ordered by anything. Your index needs to be ordered I assume? Like in the solution of @PaulDBrown
@PaulDBrown I've tested your solution. It seems, that it only works, if there are two entries per day, right? How could I do this not knowing how many entries per day?
really appreciate your help🙏
If you wish to use Direct Query, you can (NB, I've added another overlapping row to date 2/03/2021 to check if all overlapping rows are returned) :
1) Create the DateTime columns in the table using calculated columns with:
StartTime = TableDQ[date] & " " & TableDQ[start_hour] & ":" & TableDQ[start_minute]
And the equivalent for the EndTime column. Set the Data type to Date/time:
2) Create a measure to establish the row order by date/employee/task:
Sum StartTime = SUM(TableDQ[StartTime])
Order by date =
RANKX (
FILTER (
ALLEXCEPT ( TableDQ, TableDQ[employee], TableDQ[date], TableDQ[Task] ),
NOT ( ISBLANK ( [Sum StartTime] ) )
),
[Sum StartTime],
,
ASC
)
This gives you the following table visual:
3) Next create measures to establish the StartDateTime and EndDateTime for the comparison:
StartDateTime =
VAR starttime =
MAX ( TableDQ[StartTime] )
RETURN
CALCULATE (
starttime,
ALLEXCEPT ( 'TableDQ', 'TableDQ'[date], 'TableDQ'[employee], 'TableDQ'[Task] )
)
EndDateTime =
VAR PrevPeriod = [Order by date] - 1
RETURN
CALCULATE (
MAX ( TableDQ[EndTime] ),
FILTER (
ALLEXCEPT ( TableDQ, 'TableDQ'[date], 'TableDQ'[employee], TableDQ[Task] ),
[Order by date] = PrevPeriod
)
)
4) and finally the measure to identify the rows which overlap:
Indentify overlapping DQ =
VAR SelPeriod =
CALCULATE (
[Order by date],
FILTER ( TableDQ, NOT ( ISBLANK ( [EndDateTime] ) ) )
)
VAR _table =
CALCULATETABLE (
VALUES ( TableDQ[date] ),
FILTER (
TableDQ,
[Order by date] >= SelPeriod - 1
&& [Order by date] <= SelPeriod
)
)
VAR _date =
CALCULATETABLE (
VALUES ( 'TableDQ'[date] ),
FILTER ( ALL ( TableDQ ), [StartDateTime] < [EndDateTime] )
)
RETURN
COUNTROWS ( INTERSECT ( _table, _date ) )
And you will get this:
Proud to be a Super User!
Paul on Linkedin.
Can you share the .pbix file of this solution on the forum? Thanks.
Hi @SebastianAlmer ,
Yes the index needs to be in a sorted order ...preferably in ascending order.....
@PaulDBrown @jaideepnema
Really appreciate your solutions there. I might have missed the information that im working in DirectQuery mode. oops...
Do you see any easy solution with direct query? I can't create this calculated column with the "CALCULATE" function and with a measure I'm not able to user "EARLIER". Any idea? if not, then I might need to switch to imported...
thanks in advance
Hi @SebastianAlmer
Add a index column to your table and then Create two calculated column like this:
Time Flag =
var previousendhour=CALCULATE(MAX('Table'[end_hour]),FILTER(ALLEXCEPT('Table','Table'[date]),'Table'[Index]=EARLIER('Table'[Index])-1))
var previousendminute=CALCULATE(MAX('Table'[end_minute]),FILTER(ALLEXCEPT('Table','Table'[date]),'Table'[Index]=EARLIER('Table'[Index])-1))
var previousendtime= (previousendhour*100)+previousendminute
var starttime=('Table'[start_hour]*100)+'Table'[start_minute]
var timeflag=IF(starttime<previousendtime,1,0)
return timeflag
Next Time Flag = CALCULATE(MAX('Table'[Time Flag]),FILTER(ALLEXCEPT('Table','Table'[date]),'Table'[Index]=EARLIER('Table'[Index])+1))
Time Filter = IF(SUM('Table'[Time Flag])=1 || sum('Table'[Next Time Flag])=1,1,0)
Please accept this as a solution if your question has been answered !!
Appreciate a Kudos 😀
@SebastianAlmer
I'm not too sure if this will work flawlessly but...
1) Create a new columns in Power Query to return the Date StartTime and Date EndTimes per row.
2) Add a new calculated column to rank the rows by employee, date and task in ascending order based on the StartTime value:
3) Create a measure to check if a start time overlaps an end time:
Indentify overlapping =
VAR EndDateTime =
CALCULATE (
MAX ( 'Table'[End DateTime] ),
FILTER (
ALLEXCEPT ( 'Table', 'Table'[date], 'Table'[employee], 'Table'[Task] ),
'Table'[Order] = 1
)
)
VAR StartDateTime =
CALCULATE (
MAX ( 'Table'[Start DateTime] ),
FILTER (
ALLEXCEPT ( 'Table', 'Table'[date], 'Table'[employee], 'Table'[Task] ),
'Table'[Order] = 2
)
)
RETURN
IF ( StartDateTime < EndDateTime, 1 )
And you get this:
Proud to be a Super User!
Paul on Linkedin.
User | Count |
---|---|
85 | |
82 | |
65 | |
53 | |
46 |
User | Count |
---|---|
102 | |
50 | |
42 | |
39 | |
38 |