Forum Discussion

wskinner's avatar
wskinner
New Member
2 years ago
Solved

Get End Date by Next Action Date - Get Continuous Date Range by Category

Hello,

I have a question about generating an end date by only using effective dates. I can easily do this by grouping, and I have also seen how to make the 0 Index column and 1 Index column to merge a table with itself.
However, I have a specific issue causing me to have overlapping dates. It has to do with a position that changes it's manager back to a previous position that it already had.

Example:
Position "ABC123" reports to manager "BBB111" from 25-Feb-2013 until it was changed to report to manager “CCC222” on 01-Jan-2018. The position "ABC123" will continue reporting to "CCC222" from 01-Jan-2018 until 07-Sept-2021 when the reports to manager is changed back to "BBB111" where it stays reporting until currently.

 

 

Position IDReports ToEffective DateEffective End Date
ABC123BBB11125-Feb-201331-Dec-2017
ABC123CCC22201-Jan-201806-Sept-2021
ABC123BBB11107-Sept-2021 

 

A couple of issues with the data is that I’m not able to pull only when the manager changes. I have to pull all the dates for any type of changes to the position. So there are dates involved that I don’t care about. Like a position may have 3 rows and dates of various changes, but it still reports to the same manager before changing to another manager. I only want the range that the position reports to a manager.


I have a list of employee positions and the history of changes to the postion as well as the manager position it is reporting to. I want to get the date ranges a position is active and which manager position it is reporting to. I am trying to have a reference for a historical organization chart.


The ultimate purpose of this is so I can reference this table using a date, and it will tell me which positions were active that date and who did it report to at the time.

Here is a photo of what my source data looks like and what I want it to end up looking like. I will attach a file that has the data.

 

Source and Final Output

 

Here is a smaller sample data in a table for reference.

 

Position IDReports To PositionEffective Date
1234568315022/25/2013
1234568315024/6/2015
1234568315025/8/2015
1234568291621/1/2018
1234568291625/11/2020
1234568315029/7/2021
12345683150212/18/2023
2223338326126/25/2013
2223338326124/19/2015
2223338326124/21/2015

 

What the table should look like:

Position IDReports To PositionEffective DateEffective End Date
1234568315022/25/201312/31/2017
1234568291621/1/20189/6/2021
1234568315029/7/202112/18/2023
2223338326126/25/20134/21/2015

 

However I could do this in Power BI Desktop or in Excel using M Power Query.

 

Thanks for the assistance

  • Based on your description, I created data to reproduce your scenario. The pbix file is attached in the end.

    let
        Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("nZS9bsMgFIVfxfKcUi4/BuZ06dQqaqcoA0qsxFJlRzbJ0KcvEONS1TF2JA8gnQ8u59zr7TYHQhkv8lUuKXBM7IJwhAkiGKjdbMqnt/ao6+pbm6qpnzdlZ9rL3lzaMt+ttnkM4gJh5kBuN+9NVzkiWzf1tWw7u/wPSIR5AD4q81Vm65Ouj79HEwWFVwKyn1VKX9O5aU2XmeaeHOB2MMFxJS/a6OzzfNBmpHaBsHIEzCVAInA2ETpFMMY4d8+T7FF72VJ7h5twyl5KCwj2SqcsJu0NchB9JSJpVriA9oHAWClSSqWU02MOTDxkUrioQIAdyCZfEsnneRoKs0751L1Tk0+PCN9Zf80aiy0KY+j10dgi5a0YmSomJnByMAghlFI/UD23OI8AgooMXgISGEvmtdZ7U11toQdPAIAQzlgpHh2vASR9Tuye7WLpIIrZ/7mgpH0+6fYqgHN/tuq7JTmLA2GdFbO6JiJSXbP7AQ==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Position ID" = _t, #"Reports to Position" = _t, #"Effective Date" = _t, #"Workforce Action Reason Description" = _t]),
        #"Changed Type" = Table.TransformColumnTypes(Source,{{"Position ID", Int64.Type}, {"Reports to Position", Int64.Type}, {"Effective Date", type date}, {"Workforce Action Reason Description", type text}}),
        #"Filled Down" = Table.FillDown(#"Changed Type",{"Position ID"}),
        #"Grouped Rows" = 
                Table.Group(#"Filled Down", {"Position ID"},
                            {{"Count", (x)=>
                                   Table.AddColumn( Table.AddIndexColumn(  x,"Index",0,1),"nextDate", each [
                                    a=List.Buffer( x[Effective Date]&{Date.AddDays( List.Max( x[Effective Date]),1)}),
                                    b=   List.Range( a,[Index]+1,1){0},
                                    c = Date.AddDays(b,-1) ][c]    
    )
     
    
    }}),
        #"Removed Other Columns" = Table.SelectColumns(#"Grouped Rows",{"Count"}),
        #"Expanded Count" = Table.ExpandTableColumn(#"Removed Other Columns", "Count", {"Position ID", "Reports to Position", "Effective Date", "Workforce Action Reason Description", "Index", "nextDate"}, {"Position ID", "Reports to Position", "Effective Date", "Workforce Action Reason Description", "Index", "nextDate"}),
        #"Grouped Rows1" = Table.Group(#"Expanded Count", {"Position ID", "Reports to Position"}, {{"MinDate", each List.Min([Effective Date]), type nullable date}, {"MaxDate", each List.Max([nextDate]), type nullable date}},GroupKind.Local)
    in
        #"Grouped Rows1"

3 Replies

  • Based on your description, I created data to reproduce your scenario. The pbix file is attached in the end.

    let
        Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("nZS9bsMgFIVfxfKcUi4/BuZ06dQqaqcoA0qsxFJlRzbJ0KcvEONS1TF2JA8gnQ8u59zr7TYHQhkv8lUuKXBM7IJwhAkiGKjdbMqnt/ao6+pbm6qpnzdlZ9rL3lzaMt+ttnkM4gJh5kBuN+9NVzkiWzf1tWw7u/wPSIR5AD4q81Vm65Ouj79HEwWFVwKyn1VKX9O5aU2XmeaeHOB2MMFxJS/a6OzzfNBmpHaBsHIEzCVAInA2ETpFMMY4d8+T7FF72VJ7h5twyl5KCwj2SqcsJu0NchB9JSJpVriA9oHAWClSSqWU02MOTDxkUrioQIAdyCZfEsnneRoKs0751L1Tk0+PCN9Zf80aiy0KY+j10dgi5a0YmSomJnByMAghlFI/UD23OI8AgooMXgISGEvmtdZ7U11toQdPAIAQzlgpHh2vASR9Tuye7WLpIIrZ/7mgpH0+6fYqgHN/tuq7JTmLA2GdFbO6JiJSXbP7AQ==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Position ID" = _t, #"Reports to Position" = _t, #"Effective Date" = _t, #"Workforce Action Reason Description" = _t]),
        #"Changed Type" = Table.TransformColumnTypes(Source,{{"Position ID", Int64.Type}, {"Reports to Position", Int64.Type}, {"Effective Date", type date}, {"Workforce Action Reason Description", type text}}),
        #"Filled Down" = Table.FillDown(#"Changed Type",{"Position ID"}),
        #"Grouped Rows" = 
                Table.Group(#"Filled Down", {"Position ID"},
                            {{"Count", (x)=>
                                   Table.AddColumn( Table.AddIndexColumn(  x,"Index",0,1),"nextDate", each [
                                    a=List.Buffer( x[Effective Date]&{Date.AddDays( List.Max( x[Effective Date]),1)}),
                                    b=   List.Range( a,[Index]+1,1){0},
                                    c = Date.AddDays(b,-1) ][c]    
    )
     
    
    }}),
        #"Removed Other Columns" = Table.SelectColumns(#"Grouped Rows",{"Count"}),
        #"Expanded Count" = Table.ExpandTableColumn(#"Removed Other Columns", "Count", {"Position ID", "Reports to Position", "Effective Date", "Workforce Action Reason Description", "Index", "nextDate"}, {"Position ID", "Reports to Position", "Effective Date", "Workforce Action Reason Description", "Index", "nextDate"}),
        #"Grouped Rows1" = Table.Group(#"Expanded Count", {"Position ID", "Reports to Position"}, {{"MinDate", each List.Min([Effective Date]), type nullable date}, {"MaxDate", each List.Max([nextDate]), type nullable date}},GroupKind.Local)
    in
        #"Grouped Rows1"

  • dufoq3's avatar
    dufoq3
    Icon for Community Champion rankCommunity Champion

    Hi wskinner, another solution:

     

    Result

    let
        fnShift = (tbl as table, col as text, shift as nullable number, optional newColName as text, optional _type as type) as table =>
            //v 3. parametri zadaj zaporne cislo ak chces posunut riadky hore, kladne ak dole, 4. je nepovinny (novy nazov stlpca), 5. je nepovinny typ
            let
                a = Table.Column(tbl, col),
                b = if shift = 0 or shift = null then a else if shift > 0
                    then List.Repeat({null}, shift) & List.RemoveLastN(a, shift)
                    else List.RemoveFirstN(a, shift * -1) & List.Repeat({null}, shift * -1),    
                c = Table.FromColumns(Table.ToColumns(tbl) & {b}, Table.ColumnNames(tbl) &
                    ( if newColName <> null then {newColName} else
                        if shift = 0 then {col & "_Duplicate"} else
                        if shift > 0 then {col & "_PrevValue"} 
                        else              {col & "_NextValue"} )),
                d = Table.TransformColumnTypes(c, {List.Last(Table.ColumnNames(c)), if _type <> null then _type else type any})
            in
                d,
    
        fnDates = 
            (myTable as table)=>
            [
                // _Detail = GroupedRows{[#"Position ID"=123456]}[All],
                _Detail = myTable,
                _GroupedRowsLocal = Table.Group(_Detail, {"Position ID", "Reports To Position"}, {{"All", each _, type table}, {"Min", each List.Min([Effective Date]), type date}, {"Max", each List.Max([Effective Date]), type date}}, GroupKind.Local),
                _fnShiftMin = fnShift(_GroupedRowsLocal, "Min", -1, null, type date),
                _Ad_EffectiveEndDate = Table.AddColumn(_fnShiftMin, "Effective End Date", each if [Min_NextValue] <> null then Date.AddDays([Min_NextValue], -1) else [Max], type date),
                _RenamedColumn = Table.RenameColumns(_Ad_EffectiveEndDate,{{"Min", "Position#(tab)Effective Date"}}),
                _RemovedOtherColumns = Table.SelectColumns(_RenamedColumn,{"Position ID", "Position#(tab)Effective Date", "Effective End Date"})
            ][_RemovedOtherColumns],
    
        Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("dc/RCcQwDAPQXfJdUCTHvmSW0v3XaN07KOWSP8MTtrzvhbLmUbbSjV51DYIcqrRybDNviGRfsKPPWIORTDC5L9jBdNXF9oFPMhdMgXle3/KSzOwOKJiBeD337w0cT/2Ziz8/Tg==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Position ID" = _t, #"Reports To Position" = _t, #"Effective Date" = _t]),
        ChangedTypeUS = Table.TransformColumnTypes(Source,{{"Position ID", Int64.Type}, {"Reports To Position", Int64.Type}, {"Effective Date", type date}}, "en-US"),
        GroupedRows = Table.Group(ChangedTypeUS, {"Position ID"}, {{"All", fnDates, type table}}),
        Combined = Table.Combine(GroupedRows[All])
    in
        Combined
  • Thank you Ahmedx ! I was easily able to duplicate this in PowerBI and Excel. This is incredibly helpful!