PowerPivot:连接具有多个数据的表
PowerPivot: Join tables with multiple data
我不知道是否可行,但我在 PowerPivot:
中有 3 tables
每个 table 反映每个商店、每个部门和每个职能部门一名工人的历史。
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
我想像下面这样转换成一个 table,但问题是我想与日期相关联。
Per example:
用户 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
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
这给了我以下内容:
这似乎与您在问题中给出的示例相符(据我所知)。 (另外,尝试使用一些不同的数据进行测试,看看输出是否仍然正确并符合预期。)
如果输出一切正常,可以将代码精炼(以避免重复)为如下内容:
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
这给了我:
我认为这是正确的(但我不确定 logic/transformation/approach 是否尽可能高效)。
我不知道是否可行,但我在 PowerPivot:
中有 3 tables每个 table 反映每个商店、每个部门和每个职能部门一名工人的历史。
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
我想像下面这样转换成一个 table,但问题是我想与日期相关联。
Per example:
用户 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
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
这给了我以下内容:
这似乎与您在问题中给出的示例相符(据我所知)。 (另外,尝试使用一些不同的数据进行测试,看看输出是否仍然正确并符合预期。)
如果输出一切正常,可以将代码精炼(以避免重复)为如下内容:
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
这给了我:
我认为这是正确的(但我不确定 logic/transformation/approach 是否尽可能高效)。