PowerPivot:连接具有多个数据的表

时间:2019-07-03 17:02:07

标签: powerquery powerpivot

我不知道是否可能,但是我在PowerPivot中有 3个表

每个表反映了每个商店,每个部门和每个职能部门一名工人的历史。

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

这有可能吗?

谢谢

-更新-

i仅举了一个示例,其中有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 个答案:

答案 0 :(得分:1)

在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

我认为是正确的(但是我不确定逻辑/转换/方法是否像它可能的那样有效)。