Я отвечу на еще одну упрощенную задачу, поскольку не хочу обращаться к буквенным префиксам ID
.
Допустим, у нас есть следующая таблица (я включил:
ID, Group
-----------
0, A
1, A
300, B
525, C
null, A
null, B
null, B
null, C
И хотим создать новый столбец NewID
, который заменит ID
.
ID, Group, NewID
------------------
0, A, 0
1, A, 1
300, B, 300
525, C, 525
null, A, 2
null, B, 301
null, B, 302
null, C, 526
Вот метод, который использует Table.AddIndexColumn
:
let
Source = <First Table Above>,
#"Grouped Rows" = Table.Group(Source, {"Group"}, {{"ID", each List.Max([ID]), type number}}),
#"Added Custom" = Table.AddColumn(#"Grouped Rows", "Custom", (C) => Table.AddIndexColumn(Table.SelectRows(Source, each _[Group] = C[Group]),"NewID",C[ID],1)),
#"Expanded Custom" = Table.ExpandTableColumn(#"Added Custom", "Custom", {"NewID"}, {"NewID"}),
#"Removed Columns" = Table.RemoveColumns(#"Expanded Custom",{"ID"})
in
#"Removed Columns"
Сначала мы сгруппировать по Group
, чтобы найти максимальное значение ID
за Group
:
Затем мы добавляем новый столбец, в котором каждая строка столбца таблица , определенная путем фильтрации исходной таблицы до текущей группы и добавления столбца индекса, начиная с максимального значения ID
, которое мы только что нашли. Это самый сложный шаг.
Отсюда мы расширяем столбец таблицы Custom
(выбираем столбец, которого у нас еще нет) и удаляем старый столбец ID
. теперь там, где нам не хватает сортировки или набора столбцов, которые мы выбираем.
Редактировать: Я сделал ошибку в приведенном выше. Обратите внимание, что NewID
для Group
A составляет 1,2,3
вместо 0,1,2
, который я пытался.
Чтобы исправить это в этом простом примере, вы можете использовать List.Min
вместо List.Max
в пошаговом группировании.
В более сложном примере вам может потребоваться добавить столбец индекса в исходную таблицу, чтобы вы могли выполнить слияние с ним после расширения и использовать только новый NewID
для ранее NULL ID
значения, так как мы не можем гарантировать, что они являются смежными.
Вот код:
let
Source = <First Table Above>,
#"Added Index" = Table.AddIndexColumn(Source, "Index", 0, 1),
#"Grouped Rows" = Table.Group(#"Added Index", {"Group"}, {{"ID", each List.Max([ID]), type number}}),
#"Added Custom" = Table.AddColumn(#"Grouped Rows", "Custom", (C) => Table.AddIndexColumn(Table.SelectRows(Table.Sort(#"Added Index",{"ID"}), each _[Group] = C[Group]),"NewID",C[ID]+1,1)),
#"Expanded Custom" = Table.ExpandTableColumn(#"Added Custom", "Custom", {"Index", "NewID"}, {"Index", "NewID"}),
#"Merged Queries" = Table.NestedJoin(#"Added Index", {"Index"}, #"Expanded Custom", {"Index"}, "Expanded Custom", JoinKind.LeftOuter),
#"Expanded Expanded Custom" = Table.ExpandTableColumn(#"Merged Queries", "Expanded Custom", {"NewID"}, {"NewID"}),
#"Added Custom1" = Table.AddColumn(#"Expanded Expanded Custom", "ReplaceID", each if [ID] = null then [NewID] else [ID]),
#"Removed Columns" = Table.RemoveColumns(#"Added Custom1",{"ID", "NewID"})
in
#"Removed Columns"
Сложный шаг немного меняется:
(C) => Table.AddIndexColumn(
Table.SelectRows(
Table.Sort(#"Added Index", {"ID"}),
each _[Group] = C[Group]
),
"NewID", C[ID] + 1, 1
)
Разница в том, что нам нужно добавить сортировку, чтобы после всех уже назначенных ID
значений приходили значения NULL, и индексирование нуля начиналось бы с C[ID] + 1
вместо C[ID]
.
. версия, в которой меньше шагов (нет группировки, расширения или слияния), но немного более сложная функция:
let
Source = <First Table Above>,
#"Added Index" = Table.AddIndexColumn(Source, "Index", 0, 1),
#"Added Custom" = Table.AddColumn(#"Added Index", "Custom", (C) => Table.SelectRows(#"Added Index", each _[Group] = C[Group])),
#"Added NewID" = Table.AddColumn(#"Added Custom", "NewID", (C) => if C[ID] = null then Table.SelectRows(Table.AddIndexColumn(Table.SelectRows(C[Custom], each _[ID] = null), "NewID", List.Max(C[Custom][ID])+1,1), each _[Index] = C[Index]){0}[NewID] else C[ID]),
#"Removed Columns" = Table.RemoveColumns(#"Added NewID",{"Custom"})
in
#"Removed Columns"
Первый добавленный столбец Custom
- это просто индексированная исходная таблица, отфильтрованная для текущего Group
. Затем мы добавляем столбец NewID
, определенный как:
(считывание изнутри.)
(C) =>
if C[ID] = null
then Table.SelectRows(
Table.AddIndexColumn(
Table.SelectRows(C[Custom], each _[ID] = null),
"NewID", List.Max(C[Custom][ID]) + 1, 1
),
each _[Index] = C[Index]
){0}[NewID]
else C[ID]
Как и прежде, мы берем групповую подтаблицу Custom
, просто выберите пустые ID
строки и индексировать их, начиная с максимального ненулевого ID
плюс один. Это все еще оставляет нас с таблицей, поэтому мы просто хотим строку в этой подтаблице, которая соответствует Index
из всей таблицы. Мы используем {0}[NewID]
для извлечения значения из ячейки в первой (единственной) строке таблицы в столбце [NewID]
. Для ненулевых значений ID
предложение else просто оставляет их такими, какими они были.