Это довольно легко решить с помощью функций Parent-Child Hierarchy в DAX.Я не думаю, что вам нужно создавать какие-либо дополнительные таблицы, просто придерживайтесь следующих условий в ваших правилах RLS:
Для Сотрудника N
, вам просто нужно проверить, если
PATHCONTAINS(PATH('Hierarchy'[ID], 'Hierarchy'[Primary]), N)
или
PATHCONTAINS(PATH('Hierarchy'[ID], 'Hierarchy'[Secondary]), N)
Обратите внимание, что это позволяет Сотруднику 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 | | | | |
Вот код M, чтобы сделать это в редакторе Power Query:
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"
Он будет продолжать расширяться до тех пор, пока расширение до следующего уровня не выдаст все нули или не достигнет максимального количества уровней, чтобы предотвратить бесконечное зацикливание.