Forum Discussion
Zneta
2 years agoFrequent Visitor
Use Power Query to Subtract time frames form a complete day
Hello everybody, There might be an easier solution to my problem, or to not do it in Power Query at all. Any help is appreciated: I have a Dataset with start and end times like this: Start: ...
WanderingBI
2 years agoResolver III
This is tricky. You can take a look at my solution to find all the overlap times. To check the logic you can first remove all but the first two rows in my example table.
let
source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("jcy7CcAwEATRVsTFAu19NlEr4vpvwzhQYPuMnQ6PWUsMFgMc6k1tAtMg/Vkdkr3SrHTcdDT1s+Py3lXfNP9olpofWlFqk8wD", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Start = _t, End = _t]),
custom = Table.AddColumn(source, "Inner", each source),
customTypes = Table.TransformColumnTypes(custom, {{"Start", type datetime}, {"End", type datetime}}),
sourceMultiply = Table.ExpandTableColumn(customTypes, "Inner", {"Start", "End"}, {"Inner.Start", "Inner.End"}),
sourceMultiplyClean = Table.TransformColumnTypes(sourceMultiply, {{"Inner.Start", type datetime}, {"Inner.End", type datetime}}),
reorder = Table.ReorderColumns(sourceMultiplyClean, {"Start", "Inner.Start", "End", "Inner.End"}),
// Delete self-multiplied rows
reorderClean = Table.AddColumn(reorder, "IsItself", each if ([Start] = [Inner.Start] and [End] = [Inner.End]) then true else false),
reorderCleanFiltered = Table.SelectRows(reorderClean, each ([IsItself] = false)),
// functions for minDate, maxDate
minDate = (date1, date2)=> if date1 < date2 then date1 else date2,
maxDate = (date1, date2)=> if date1 >= date2 then date1 else date2,
// Columns for minEnd and maxStart
minEnd = Table.AddColumn(reorderCleanFiltered,"MinEnd", each minDate([End],[Inner.End]), type datetime),
maxStart = Table.AddColumn(minEnd, "MaxStart", each maxDate([Start], [Inner.Start]), type datetime ),
// Calculate time difference
durationColumn = Table.AddColumn(maxStart, "Duration", each [MinEnd] - [MaxStart], type duration),
durationGreaterZero = Table.SelectRows(durationColumn, each [Duration] > #duration(0, 0, 0, 0)),
// delete doubles
keepDistinct = Table.Distinct(durationGreaterZero, {"MinEnd","MaxStart"})
in
keepDistinct
You could then first calculate your durations between faults per day and then substract the overlaps for each day.
1. Add a column that holds the full source table.
2. Expand "Inner.Start" and "Inner.End"
3. Find the minimum end of each event.
4. Find the maximum start of each event.
5. Calculate duration
6. No overlap -> negative duration -> delete rows
6. Delete where the row multiplied by itself.
7. The overlap time will be produced twice, so keep only distinct.
Example as follows:
I am not completely sure if it catches all scenarios. Please test extensively.