Я хотел бы иметь максимальную и минимальную дату различных типов отсутствия для каждого сотрудника проекта. Я хотел бы иметь это в Power BI, но не знаю, как это сделать.
Есть 3 столбца, которые следует сгруппировать: идентификатор проекта, идентификатор человека и статус времени.
Я думал о группировке также по месяцу и году, но тогда, если возникнет ситуация, когда в одном месяце будет два больничных, это не будет работать должным образом. Вот пример данных:
И результат должен быть таким:
Спасибо.
Вот образец данных:
Project ID Person ID Time Status Date
10 1 Sick leave 21.06.2024
10 1 Sick leave 09.07.2024
10 1 Sick leave 10.07.2024
10 1 Sick leave 11.07.2024
10 1 Sick leave 12.07.2024
9 2 Annual leave 12.08.2024
9 2 Annual leave 13.08.2024
9 2 Annual leave 14.08.2024
9 2 Annual leave 15.08.2024
9 2 Annual leave 31.08.2024
я добавил это
В SQL такого рода проблемы называются «Пробелы и острова» и обычно решаются с помощью оконных функций и PARTITION BY. Возможно, вы могли бы сделать что-то неуклюжее в M с упорядочиванием по идентификатору проекта, идентификатору человека, временному статусу, дате, а затем AddIndexColumn и самостоятельному присоединению, но похоже, что в DAX есть оконные функции.
Как определить, когда заканчивается один отпуск и начинается второй больничный, если отпусков несколько?
Я только хотел сгруппировать то, что происходит по дням





let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Project ID", Int64.Type}, {"Person ID", Int64.Type}, {"Time Status", type text}, {"Date", type date}}),
#"Added Custom" = Table.AddColumn(#"Changed Type", "Sequence", each try if Value.Is( Record.Field( #"Changed Type"{[Project ID = [Project ID], Date = Date.AddDays( [Date],-1)] }, "Date") , type date) then null else [Date] otherwise [Date]),
#"Filled Down" = Table.FillDown(#"Added Custom",{"Sequence"}),
#"Grouped Rows" = Table.Group(#"Filled Down", {"Project ID", "Person ID", "Time Status", "Sequence"}, {{"Start", each List.Min([Date]), type date}, {"End", each List.Max([Date]), type date}}),
#"Renamed Columns" = Table.RenameColumns(#"Grouped Rows",{{"Sequence", "Date"}}),
#"Changed Type1" = Table.TransformColumnTypes(#"Renamed Columns",{{"Date", type date}})
in
#"Changed Type1"
Он не работает для большого объема данных, возвращает дату в столбце «Последовательность».
Я думал, что другое решение сработало для вас, поскольку вы приняли его как ответ? Это решение работает с вашими примерными данными, поэтому добавьте больше данных, чтобы показать, где оно не работает, чтобы протестировать его или попробовать решение Рона.
Да да, я просто хотел ответить на все ваши идеи, но спасибо за усилия, я не проверяю решение Рона
Это должно возвращать дату в столбце последовательности. Я не использую индекс, поскольку в этом нет необходимости, если у нас уже есть дата. Затем столбец последовательности переименовывается по дате, чтобы соответствовать ожидаемым результатам.
Я добавил функцию GetStartAndEndDates для проверки дат[i]-dates[i-1] для каждого projectId, personId и timeStatus.
Если date[i]-dates[i-1] > 1, я предполагаю, что date[i] — это начало нового «отпуска».
let
Source = Excel.CurrentWorkbook(),
Navigation = Source{[Name = "Table1"]}[Content],
GetStartAndEndDates = (source as table)=>
let
sorted = Table.Sort(source, {{"Date", Order.Ascending}}),
addIndex = Table.AddIndexColumn(sorted, "Index", 0, 1, Int64.Type),
addDuration = Table.AddColumn(addIndex, "Duration", each if [Index] = 0 then 0 else Duration.Days([Date] - addIndex[Date]{[Index]-1}) ),
addKey = Table.AddColumn(addDuration, "Key", each if [Index] = 0 then 0 else if [Duration] <= 1 then null else [Index]),
filled = Table.FillDown(addKey, {"Key"}),
results = Table.Group(filled, {"Key"}, {{"Start Date", each List.Min([Date]), type nullable date}, {"End Date", each List.Max([Date]), type nullable date}})
in
results,
grouped = Table.Group(Navigation, {"Project ID", "Person ID", "Time Status"}, {{"All", each _, type nullable table[#"Project ID" = any, #"Person ID" = any, #"Time Status" = any, Date = any]}}),
startEndDates = Table.AddColumn(grouped, "StartEndDates", each GetStartAndEndDates([All])),
expanded = Table.ExpandTableColumn(startEndDates, "StartEndDates", {"Start Date", "End Date"}, {"Start Date", "End Date"}),
removed = Table.RemoveColumns(expanded, {"All"})
in
removed
Если у вас большой набор данных, следующие действия будут выполняться значительно быстрее.
Предполагается, что данные уже отсортированы, как показано в вашем примере, — по датам по возрастанию внутри каждого Project ID | Person ID. Если это не так, то их необходимо будет отсортировать, что увеличит время обработки.
Он использует столбец Index и 4-й и 5-й аргументы функции Table.Group, чтобы обеспечить группировку по последовательным датам:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{
{"Project ID", Int64.Type}, {"Person ID", Int64.Type}, {"Time Status", type text}, {"Date", type date}}),
#"Added Index" = Table.AddIndexColumn(#"Changed Type", "Index", 0, 1, Int64.Type),
#"Grouped Rows" = Table.Group(#"Added Index", {"Project ID", "Person ID", "Time Status","Date", "Index"}, {
{"Start Date", each List.Min([Date]), type date},
{"End Date", each List.Max([Date]), type date}
}, GroupKind.Local,(x,y)=>Duration.Days(y[Date]-x[Date])- (y[Index]-x[Index]) ),
#"Removed Columns" = Table.RemoveColumns(#"Grouped Rows",{"Index"})
in
#"Removed Columns"
Умное решение, Рон, проголосовали за.
Действительно хорошее решение, к тому же очень быстрое, спасибо
Можете ли вы вставить свои данные в виде копируемого текста уценки?