Forum Discussion

SadStatue's avatar
SadStatue
Helper II
5 years ago
Solved

Identifying Broken Shifts

Hi Everyone,

 

I have a list of shifts and the Employees. I want to identify all the shifts that has less than 8 hours gap between them for each Employee.

sample: I want to calculate the last two column (Is broken Shift?, Broken Shift ID). does anyone can help me to deal with it?

Start Date Time========End Date Time=======Shift IDEmp ID AdjIs Shift broken?Broken shift ID
26/04/2021 7:30:00 AM26/04/2021 3:00:00 PM1006073204492  
27/04/2021 10:00:00 AM27/04/2021 1:00:00 PM1006169204492Y1006169
27/04/2021 3:00:00 PM27/04/2021 9:30:00 PM1006074204492Y1006169
28/04/2021 3:00:00 PM28/04/2021 10:00:00 PM1000915204492  
29/04/2021 3:00:00 PM29/04/2021 9:30:00 PM1006076204492Y1006075
29/04/2021 6:30:00 AM29/04/2021 9:30:00 AM1006075204492Y1006075
29/04/2021 9:45:00 AM29/04/2021 2:00:00 PM1008080203374  

 

You can find the larger sample data here!

 

Thanks for your help.

  • Anonymous's avatar
    Anonymous
    5 years ago

    Just put this into the Advanced Editor in Power Query and investigate the steps one by one... This does what you want. How to extract the relevant shift id's from it? That's what I leave to you as an exercise 🙂

     

    // Shifts
    let
        Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("pZBBCsQgDEWvIq4L/YlVa3ejxyi9/zVGKBRnkkUlu/DJ4yfvPD2DacW2cnLIR8AB+GVMKfboTglIyKFPH38tA5sd4dka0/DDUioqGzWW6bnm7t0ku6vs7pjHXhSKki0OSf7b0/LXq7Jab5E3J8lOea4Gz5J977kaPFeDZ8FOeK4Gz83gWbLvPTeD52bwLNgJz529vg==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Start Time" = _t, #"End Time" = _t, ShiftID = _t, EmpID = _t]),
        #"Changed Type" = Table.TransformColumnTypes(Source,{{"Start Time", type datetime}, {"End Time", type datetime}, {"ShiftID", Int64.Type}, {"EmpID", type text}}),
        #"Sorted Rows" = Table.Sort(#"Changed Type",{{"EmpID", Order.Ascending}, {"Start Time", Order.Ascending}}),
        #"Added Index" = Table.AddIndexColumn(#"Sorted Rows", "Index", 0, 1, Int64.Type),
        #"Reordered Columns" = Table.ReorderColumns(#"Added Index",{"Index", "Start Time", "End Time", "ShiftID", "EmpID"}),
        #"Added Custom" = Table.AddColumn(#"Reordered Columns", "PrevShiftEndTime", 
            each 
            List.First(
                Table.SelectRows(
                    #"Reordered Columns",
                    (inner) => inner[Index] + 1 = [Index] and inner[EmpID] = [EmpID]
                )[End Time],
                null
            )
        ),
        #"Added Custom1" = Table.AddColumn(#"Added Custom", "Delta < 8 hrs",
            each [Start Time] - [PrevShiftEndTime] < #duration(0, 8, 0, 0)
        ),
        #"Added Custom2" = Table.AddColumn(#"Added Custom1", "Shift Broken? (1)",
            each if not ( [#"Delta < 8 hrs"] is null ) and [#"Delta < 8 hrs"] then "Y" else null
        ),
        #"Added Custom3" = Table.AddColumn(#"Added Custom2", "Shift Broken?", 
            each 
            let
                NextRowShiftBrokenStatus = List.First(
                    Table.SelectRows(
                        #"Added Custom2",
                        (inner) => inner[Index] = [Index] + 1 and inner[EmpID] = [EmpID]
                    )[#"Shift Broken? (1)"],
                    null
                ),
                Output = 
                    if ( NextRowShiftBrokenStatus = "Y" or [#"Shift Broken? (1)"] = "Y" )
                    then "Y" else null
            in
                Output
        ),
        #"Removed Columns" = Table.RemoveColumns(#"Added Custom3",{"Index", "PrevShiftEndTime", "Delta < 8 hrs", "Shift Broken? (1)"})
    in
        #"Removed Columns"

     

5 Replies

  • Anonymous's avatar
    Anonymous
    Not applicable

    Just put this into the Advanced Editor in Power Query and investigate the steps one by one... This does what you want. How to extract the relevant shift id's from it? That's what I leave to you as an exercise 🙂

     

    // Shifts
    let
        Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("pZBBCsQgDEWvIq4L/YlVa3ejxyi9/zVGKBRnkkUlu/DJ4yfvPD2DacW2cnLIR8AB+GVMKfboTglIyKFPH38tA5sd4dka0/DDUioqGzWW6bnm7t0ku6vs7pjHXhSKki0OSf7b0/LXq7Jab5E3J8lOea4Gz5J977kaPFeDZ8FOeK4Gz83gWbLvPTeD52bwLNgJz529vg==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Start Time" = _t, #"End Time" = _t, ShiftID = _t, EmpID = _t]),
        #"Changed Type" = Table.TransformColumnTypes(Source,{{"Start Time", type datetime}, {"End Time", type datetime}, {"ShiftID", Int64.Type}, {"EmpID", type text}}),
        #"Sorted Rows" = Table.Sort(#"Changed Type",{{"EmpID", Order.Ascending}, {"Start Time", Order.Ascending}}),
        #"Added Index" = Table.AddIndexColumn(#"Sorted Rows", "Index", 0, 1, Int64.Type),
        #"Reordered Columns" = Table.ReorderColumns(#"Added Index",{"Index", "Start Time", "End Time", "ShiftID", "EmpID"}),
        #"Added Custom" = Table.AddColumn(#"Reordered Columns", "PrevShiftEndTime", 
            each 
            List.First(
                Table.SelectRows(
                    #"Reordered Columns",
                    (inner) => inner[Index] + 1 = [Index] and inner[EmpID] = [EmpID]
                )[End Time],
                null
            )
        ),
        #"Added Custom1" = Table.AddColumn(#"Added Custom", "Delta < 8 hrs",
            each [Start Time] - [PrevShiftEndTime] < #duration(0, 8, 0, 0)
        ),
        #"Added Custom2" = Table.AddColumn(#"Added Custom1", "Shift Broken? (1)",
            each if not ( [#"Delta < 8 hrs"] is null ) and [#"Delta < 8 hrs"] then "Y" else null
        ),
        #"Added Custom3" = Table.AddColumn(#"Added Custom2", "Shift Broken?", 
            each 
            let
                NextRowShiftBrokenStatus = List.First(
                    Table.SelectRows(
                        #"Added Custom2",
                        (inner) => inner[Index] = [Index] + 1 and inner[EmpID] = [EmpID]
                    )[#"Shift Broken? (1)"],
                    null
                ),
                Output = 
                    if ( NextRowShiftBrokenStatus = "Y" or [#"Shift Broken? (1)"] = "Y" )
                    then "Y" else null
            in
                Output
        ),
        #"Removed Columns" = Table.RemoveColumns(#"Added Custom3",{"Index", "PrevShiftEndTime", "Delta < 8 hrs", "Shift Broken? (1)"})
    in
        #"Removed Columns"

     

    • SadStatue's avatar
      SadStatue
      Helper II

      Hi Anonymous 

      thanks for your quick help!

      This inner join worked well. I haven't used it in M.

      It seems that works well.

      Cheers,

    • SadStatue's avatar
      SadStatue
      Helper II

      HIAnonymous 

      Thanks for your solution. I implemented what you suggested. So I can recognise the broken shift, but I still have issue in group all the related broken shift. its hard to get Min/Max index for the related shifts. I think I need a variable with a loop to find it.

      I would be happy if u can help on the next step.

      Cheers,

  • Anonymous's avatar
    Anonymous
    Not applicable

    I understand you just want a column in the base table? If this is the requirement, then this should be rather easy to calculate in Power Query. I also understand that for any given individual the shifts are never overlapping, right?

    • SadStatue's avatar
      SadStatue
      Helper II

      Hi Anonymous ,

      Thanks for your reply!

      I want to define these two columns (Is broken Shift?, Broken Shift ID), no matter in DAX or Power Query.

      Yes, its right shifts cannot overlap for the same Employee.

      Cheers,