PowerPivot: объединение таблиц с несколькими данными - PullRequest
0 голосов
/ 03 июля 2019

Я не знаю, возможно ли это, но у меня есть 3 таблицы в PowerPivot :

каждая таблица отражает историю одного работника на магазин, на отдел и на функцию.

User    Store   DateChangeStore
User 1  Store 1 01/01/2019
User 1  Store 2 01/05/2019

User    Dept    DateChangeDpt
User 1  Dept 1  01/01/2019
User 1  Dept 2  01/03/2019
User 1  Dept 1  01/06/2019

User    Function DateChangeFct
User 1  Func 1   01/01/2019
User 1  Func 2   01/02/2019

И я хочу преобразовать в одну таблицу, как показано ниже, но суть в том, что я хочу связать с датой.

За пример:

пользователь 1 при входе был в магазине 1, отдел 1 с функцией 1. Но когда он переключился на функцию 2, он все еще был в магазине 1 и отделе 1 ...

Можно увидеть по дате изменения.

User    Store   DateChangeStore Dept    DateChangeDpt   Function    DateChangeFct
User 1  Store 1 01/01/2019      Dept 1  01/01/2019      Func 1     01/01/2019
User 1  Store 1 01/01/2019      Dept 1  01/01/2019      Func 2     01/02/2019
User 1  Store 1 01/01/2019      Dept 2  01/03/2019      Func 2     01/02/2019
User 1  Store 2 01/05/2019      Dept 2  01/03/2019      Func 2     01/02/2019
User 1  Store 2 01/05/2019      Dept 1  01/06/2019      Func 2     01/02/2019

Возможно ли это каким-либо образом?

спасибо

- ОБНОВЛЕНИЕ -

Я привел пример только с 1 пользователем, но исходные данные для нескольких пользователей:

пример ниже

User    Store   DateChangeStore
User 1  Store 1 01/01/2019
User 1  Store 2 01/05/2019
User 2	Store 1	01/06/2019

User    Dept    DateChangeDpt
User 1  Dept 1  01/01/2019
User 1  Dept 2  01/03/2019
User 1  Dept 3  01/06/2019
User 2 	Dept 1	01/06/2019
User 2	Dept 2	01/07/2019

User    Function DateChangeFct
User 1  Func 1   01/01/2019
User 1  Func 2   01/02/2019
User 2	Func 1	01/06/2019

1 Ответ

1 голос
/ 04 июля 2019

Первоначальная попытка решения в Power Query может выглядеть примерно так:

let
    storeTable = Table.FromColumns({{"User 1", "User 1"}, {"Store 1", "Store 2"}, {#date(2019, 1, 1), #date(2019, 5, 1)}}, {"User", "Store", "DateChangeStore"}),
    deptTable = Table.FromColumns({{"User 1", "User 1", "User 1"}, {"Dept 1", "Dept 2", "Dept 3"}, {#date(2019, 1, 1), #date(2019, 3, 1), #date(2019,6,1)}}, {"User", "Dept", "DateChangeDept"}),
    funcTable = Table.FromColumns({{"User 1", "User 1"}, {"Func 1", "Func 2"}, {#date(2019, 1, 1), #date(2019, 2, 1)}}, {"User", "Function", "DateChangeFct"}),
    distinctDates = List.Distinct(storeTable[DateChangeStore] & deptTable[DateChangeDept] & funcTable[DateChangeFct]),
    columnOfDates = Table.FromColumns({distinctDates}, type table [changeDate = date]),
    joinedStore = Table.NestedJoin(columnOfDates, {"changeDate"}, storeTable, {"DateChangeStore"}, "toExpand", JoinKind.LeftOuter),
    expandedStore = Table.ExpandTableColumn(joinedStore, "toExpand", {"User", "Store", "DateChangeStore"}, {"User", "Store", "DateChangeStore"}),
    joinedDept = Table.NestedJoin(expandedStore, {"changeDate"}, deptTable, {"DateChangeDept"}, "toExpand", JoinKind.LeftOuter),
    expandedDept = Table.ExpandTableColumn(joinedDept, "toExpand", {"DateChangeDept"}),
    joinedFunction = Table.NestedJoin(expandedDept, {"changeDate"}, funcTable, {"DateChangeFct"}, "toExpand", JoinKind.LeftOuter),
    expandedFunction = Table.ExpandTableColumn(joinedFunction, "toExpand", {"DateChangeFct"}),
    sorted = Table.Sort(expandedFunction,{{"changeDate", Order.Ascending}}),
    filledDown = Table.FillDown(sorted,{"User", "Store", "DateChangeStore", "DateChangeDept", "DateChangeFct"})
in
    filledDown

, что дает мне следующее:

Output table

, что соответствует примеру, который вы дали в своем вопросе (насколько я вижу).(Также попробуйте выполнить тестирование с использованием различных данных, чтобы убедиться, что вывод по-прежнему корректен и, как и ожидалось.)

Если с выводом все в порядке, код можно усовершенствовать (чтобы избежать повторения), например:

let
    // You don't need the lines below (I only use them to generate the data in the example). You should replace them with your own tables/code.
    storeTable = Table.FromColumns({{"User 1", "User 1"}, {"Store 1", "Store 2"}, {#date(2019, 1, 1), #date(2019, 5, 1)}}, {"User", "Store", "DateChangeStore"}),
    deptTable = Table.FromColumns({{"User 1", "User 1", "User 1"}, {"Dept 1", "Dept 2", "Dept 3"}, {#date(2019, 1, 1), #date(2019, 3, 1), #date(2019,6,1)}}, {"User", "Dept", "DateChangeDept"}),
    funcTable = Table.FromColumns({{"User 1", "User 1"}, {"Func 1", "Func 2"}, {#date(2019, 1, 1), #date(2019, 2, 1)}}, {"User", "Function", "DateChangeFct"}),

    columnOfDates = 
        let
            allDates = storeTable[DateChangeStore] & deptTable[DateChangeDept] & funcTable[DateChangeFct],
            deduplicated = List.Distinct(allDates),
            asTable = Table.FromColumns({deduplicated}, type table [changeDate = date])
        in asTable,
    LeftJoinAndExpand = (leftTable as table, leftJoinColumn as text, rightTable, rightJoinColumn, expandAllInRightTable as logical) =>
        let
            joined = Table.NestedJoin(leftTable, {leftJoinColumn}, rightTable, {rightJoinColumn}, "$toExpand", JoinKind.LeftOuter),
            columnsToExpand = if expandAllInRightTable then Table.ColumnNames(rightTable) else {rightJoinColumn},
            expanded = Table.ExpandTableColumn(joined, "$toExpand", columnsToExpand)
        in expanded,
    joinedStore = LeftJoinAndExpand(columnOfDates, "changeDate", storeTable, "DateChangeStore", true),
    joinedDept = LeftJoinAndExpand(joinedStore, "changeDate", deptTable, "DateChangeDept", false),
    joinedFunc = LeftJoinAndExpand(joinedDept, "changeDate", funcTable, "DateChangeFct", false),
    sorted = Table.Sort(joinedFunc, {{"changeDate", Order.Ascending}}),
    filledDown = Table.FillDown(sorted, {"User", "Store", "DateChangeStore", "DateChangeDept", "DateChangeFct"})
in
    filledDown

И для нескольких пользователей:

Вы можете попробовать что-то вроде:

let
    storeTable = Table.FromColumns({{"User 1", "User 1", "User 2"}, {"Store 1", "Store 2", "Store 1"}, {#date(2019, 1, 1), #date(2019, 5, 1), #date(2019, 6, 1)}}, type table [User = text, Store = text, DateChangeStore = date]),
    deptTable = Table.FromColumns({{"User 1", "User 1", "User 1", "User 2", "User 2"}, {"Dept 1", "Dept 2", "Dept 3", "Dept 1", "Dept 2"}, {#date(2019, 1, 1), #date(2019, 3, 1), #date(2019, 6, 1), #date(2019, 6, 1), #date(2019, 7, 1)}}, type table [User = text, Dept = text, DateChangeDept = date]),
    funcTable = Table.FromColumns({{"User 1", "User 1", "User 2"}, {"Func 1", "Func 2", "Func 1"}, {#date(2019, 1, 1), #date(2019, 2, 1), #date(2019, 6, 1)}}, type table [User = text, Function = text, DateChangeFct = date]),
    // You don't need the lines above (I only use them to generate the data in the example).
    // You should replace them with your own tables/code.

    renamePairs = {{"DateChangeStore", "$changeDate"}, {"DateChangeDept", "$changeDate"}, {"DateChangeFct", "$changeDate"}},
    toCombine = List.Transform({storeTable, deptTable, funcTable}, each Table.SelectColumns(Table.RenameColumns(_, renamePairs, MissingField.Ignore), {"User", "$changeDate"})),
    combined = Table.Distinct(Table.Combine(toCombine), {"User", "$changeDate"}),
    LeftJoinAndExpand = (leftTable as table, leftJoinKeys as list, rightTable as table, rightJoinKeys as list) as table =>
        let
            joined = Table.NestedJoin(leftTable, leftJoinKeys, rightTable, rightJoinKeys, "$toExpand", JoinKind.LeftOuter),
            columnsToExpand = List.Difference(Table.ColumnNames(rightTable), Table.ColumnNames(leftTable)),
            expanded = Table.ExpandTableColumn(joined, "$toExpand", columnsToExpand)
        in expanded,
    groupedAndJoined = Table.Group(combined, {"User"}, {"$toExpand", (userTable) => 
            let
                joinedStore = LeftJoinAndExpand(userTable, {"User", "$changeDate"}, storeTable, {"User", "DateChangeStore"}),
                joinedDept = LeftJoinAndExpand(joinedStore, {"User", "$changeDate"}, deptTable, {"User", "DateChangeDept"}),
                joinedFunc = LeftJoinAndExpand(joinedDept, {"User", "$changeDate"}, funcTable, {"User", "DateChangeFct"})
            in joinedFunc
        , type table}),

    // Am doing this as a separate step (rather than in previous step) only so that the JOIN results can be previewed in Query Editor.
    fillDownNestedTables = Table.TransformColumns(groupedAndJoined, {"$toExpand", (userTable) => 
            let
                sorted = Table.Sort(userTable, {{"User", Order.Ascending}, {"$changeDate", Order.Ascending}}),
                columnsToFill = List.RemoveMatchingItems(Table.ColumnNames(sorted), {"User", "$changeDate"}),
                filledDown = Table.FillDown(sorted, columnsToFill),
                dropHelperColumn = Table.RemoveColumns(filledDown, {"$changeDate"})
            in dropHelperColumn 
        , type table}),
    expandNestedTables = 
        let
            allHeaders = List.Combine(List.Transform(Table.Column(fillDownNestedTables, "$toExpand"), Table.ColumnNames)),
            columnsToExpand = List.Difference(List.Distinct(allHeaders), Table.ColumnNames(fillDownNestedTables)),
            expanded = Table.ExpandTableColumn(fillDownNestedTables, "$toExpand", columnsToExpand)
        in expanded 
in
    expandNestedTables

, что дает мне:

Multiple users output

, что я считаю правильным (но я не уверен, что логика / преобразование / подход настолько эффективны, насколько это возможно).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...