使用 DAX 中的父子层次结构函数很容易解决这个问题。我认为您不需要构建任何额外的表,只需在您的 RLS 规则中添加以下条件:
对于员工N,您只需检查是否
PATHCONTAINS(PATH('Hierarchy'[ID], 'Hierarchy'[Primary]), N)
或
PATHCONTAINS(PATH('Hierarchy'[ID], 'Hierarchy'[Secondary]), N)
请注意,这允许 Employee N 看到他们自己以及他们的下属,但如果您不希望这样,您可以添加一个额外的条件。
编辑:当你的结构不是一棵树时,问题变得更加困难。这是一种应该可行的方法。
对于每个ID,查找下属得到Level1,搜索Level1下一级下属,以此类推,直到没有下属。 (如果你的结构中有一个循环让你回到更高的层次,那么你就会陷入递归。)
在这种情况下,顶部下方有三个级别,因此我们需要三个步骤。
| ID | Primary | Secondary | Level1 | Level2 | Level3 |
|----|---------|-----------|--------|--------|--------|
| 0 | | | 1 | 4 | 6 |
| 0 | | | 2 | 4 | 6 |
| 0 | | | 2 | 5 | |
| 0 | | | 3 | | |
| 1 | 0 | | 4 | 6 | |
| 2 | 0 | | 4 | 6 | |
| 2 | 0 | | 5 | | |
| 3 | 0 | | | | |
| 4 | 1 | 2 | 6 | | |
| 5 | 2 | | | | |
| 6 | 4 | | | | |
这是在 Power Query 编辑器中执行此操作的 M 代码:
let
Source = Table.FromRows({{0,null,null},{1,0,null},{2,0,null},{3,0,null},{4,1,2},{5,2,null},{6,4,null}},{"ID", "Primary", "Secondary"}),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"ID", Int64.Type}, {"Primary", Int64.Type}, {"Secondary", Int64.Type}}),
SearchNextLevel = ExpandNext(ExpandNext(ExpandNext(#"Changed Type", "Level1", "ID"), "Level2", "Level1"), "Level3", "Level2"),
#"Appended Query" =
Table.Combine(
{Table.RenameColumns(Table.SelectColumns(SearchNextLevel, {"ID", "Level1"}), {"Level1","Subordinate"}),
Table.RenameColumns(Table.SelectColumns(SearchNextLevel, {"ID", "Level2"}), {"Level2","Subordinate"}),
Table.RenameColumns(Table.SelectColumns(SearchNextLevel, {"ID", "Level3"}), {"Level3","Subordinate"})}
),
#"Filtered Rows" = Table.SelectRows(#"Appended Query", each ([Subordinate] <> null)),
#"Removed Duplicates" = Table.Distinct(#"Filtered Rows"),
#"Sorted Rows" = Table.Sort(#"Removed Duplicates",{{"ID", Order.Ascending}, {"Subordinate", Order.Ascending}})
in
#"Sorted Rows"
这是多次使用以扩展至下一个级别的自定义函数:
let
ExpandToNextLevel = (T as table, NextLevel as text, ThisLevel as text) as table =>
let
SearchNextLevel =
Table.AddColumn(T,
NextLevel,
(C) =>
Table.SelectRows(
T, each Record.Field(C, ThisLevel) <> null and
([Primary] = Record.Field(C, ThisLevel) or
[Secondary] = Record.Field(C, ThisLevel))
)[ID]
),
ExpandColumn = Table.ExpandListColumn(SearchNextLevel, NextLevel)
in
ExpandColumn
in
ExpandToNextLevel
为了通用,我显然需要将扩展和追加放入递归循环中。如果时间允许,我会回到这个。
编辑:这是查询的递归版本,它使用反透视而不是追加。
let
Source = Table.FromRows({{0,null,null},{1,0,null},{2,0,null},{3,0,null},{4,1,2},{5,2,null},{6,4,null}},{"ID", "Primary", "Secondary"}),
#"Changed Types" = Table.TransformColumnTypes(Source,{{"ID", Int64.Type}, {"Primary", Int64.Type}, {"Secondary", Int64.Type}}),
IDCount = List.Count(List.Distinct(#"Changed Types"[ID])),
RecursiveExpand = List.Generate(
() => [i=0, InputTable = #"Changed Types"],
each [i] < IDCount and
List.NonNullCount(List.Last(Table.ToColumns([InputTable]))) > 0,
each [
CurrentLevel = if [i] = 0 then "ID" else "Level" & Text.From([i]),
NextLevel = if [i] = 0 then "Level1" else "Level" & Text.From([i]+1),
InputTable = ExpandNext([InputTable], NextLevel, CurrentLevel),
i = [i] + 1
]
),
FinalTable = List.Last(RecursiveExpand)[InputTable],
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(FinalTable, {"Secondary", "Primary", "ID"}, "Level", "Subordinate"),
#"Removed Other Columns" = Table.SelectColumns(#"Unpivoted Other Columns",{"ID", "Subordinate"}),
#"Removed Duplicates" = Table.Distinct(#"Removed Other Columns"),
#"Sorted Rows" = Table.Sort(#"Removed Duplicates",{{"ID", Order.Ascending}, {"Subordinate", Order.Ascending}})
in
#"Sorted Rows"
它将不断扩展关卡,直到扩展至下一个关卡产生所有空值或达到最大关卡数以防止无限循环。