Power BI中如何筛选并调整并行工作时间数据行
解决方案:处理Power BI中的并行工作记录时间拆分
针对你遇到的并行工作记录(起止时间相同、仅TimeOfWork和并行参数不同)的时间调整需求,以下提供两种可行方案,均无需修改原系统的输入输出:
方案一:Power Query预处理数据(推荐,适合导出至其他系统)
通过Power Query批量转换数据,直接生成调整后的起止时间,处理后的数据可直接导出给其他系统,不会被识别为重复项。
步骤&代码示例
假设你的数据表名为EmployeeWorkRecords,包含列:EmployeeID、Prichod(开始时间)、Odchod(结束时间)、JOBID、ParallelParam(并行参数)、TimeOfWork(工作时长,单位:分钟)
- 进入Power Query编辑器,替换现有查询为以下M代码:
let Source = EmployeeWorkRecords, // 按员工ID、起止时间分组,计算组内总工作时长并保留组内所有行 GroupedData = Table.Group(Source, {"EmployeeID", "Prichod", "Odchod"}, { {"TotalGroupTime", each List.Sum([TimeOfWork]), type number}, {"GroupRows", each _, type table [EmployeeID=text, Prichod=datetime, Odchod=datetime, JOBID=text, ParallelParam=text, TimeOfWork=number]} }), // 处理每组内的并行记录,计算新的起止时间 ProcessParallelGroups = Table.TransformColumns(GroupedData, {"GroupRows", (rows) => let // 按并行参数排序(可根据实际需求替换为JOBID或其他字段) SortedRows = Table.Sort(rows, {"ParallelParam", Order.Ascending}), // 添加累计工作时长(含当前行) AddCumulativeTime = Table.AddColumn(SortedRows, "CumulativeTime", each List.Sum(List.FirstN(SortedRows[TimeOfWork], Table.PositionOf(SortedRows, _)+1))), // 添加当前行之前的累计工作时长 AddPreviousCumulative = Table.AddColumn(AddCumulativeTime, "PreviousCumulative", each if Table.PositionOf(AddCumulativeTime, _)=0 then 0 else List.Sum(List.FirstN(SortedRows[TimeOfWork], Table.PositionOf(AddCumulativeTime, _)))), // 计算该组的总时间跨度(分钟) TotalDuration = Duration.TotalMinutes(rows[Odchod]{0} - rows[Prichod]{0}), // 生成新的开始时间 AddNewPrichod = Table.AddColumn(AddPreviousCumulative, "NewPrichod", each rows[Prichod]{0} + #duration(0,0,0, ( [PreviousCumulative] / rows[TotalGroupTime]{0} ) * TotalDuration )), // 生成新的结束时间 AddNewOdchod = Table.AddColumn(AddNewPrichod, "NewOdchod", each rows[Prichod]{0} + #duration(0,0,0, ( [CumulativeTime] / rows[TotalGroupTime]{0} ) * TotalDuration )), // 清理临时列并替换原起止时间列 CleanUpColumns = Table.RemoveColumns(AddNewOdchod, {"Prichod", "Odchod", "CumulativeTime", "PreviousCumulative"}), RenameFinalColumns = Table.RenameColumns(CleanUpColumns, {{"NewPrichod", "Prichod"}, {"NewOdchod", "Odchod"}}) in RenameFinalColumns }), // 展开处理后的行数据 ExpandedRows = Table.ExpandTableColumn(ProcessParallelGroups, "GroupRows", {"JOBID", "ParallelParam", "TimeOfWork", "Prichod", "Odchod"}), // 移除临时计算列(可选) FinalTable = Table.RemoveColumns(ExpandedRows, {"TotalGroupTime"}) in FinalTable
- 运行查询后,即可得到调整后的记录:并行任务的起止时间会按
TimeOfWork的占比依次拆分,不会再出现重复的时间区间。
方案二:DAX计算列(适合Power BI报表内展示)
如果仅需在Power BI报表中展示调整后的时间,无需修改源数据,可通过DAX创建计算列实现:
计算列代码
- 计算同一员工、同一时间组的总工作时长:
TotalGroupTime = CALCULATE( SUM('EmployeeWorkRecords'[TimeOfWork]), ALLEXCEPT('EmployeeWorkRecords', 'EmployeeWorkRecords'[EmployeeID], 'EmployeeWorkRecords'[Prichod], 'EmployeeWorkRecords'[Odchod]) )
- 计算当前行在组内的累计工作时长(按并行参数排序):
CumulativeTime = VAR CurrentParam = 'EmployeeWorkRecords'[ParallelParam] VAR GroupParams = CALCULATETABLE( VALUES('EmployeeWorkRecords'[ParallelParam]), ALLEXCEPT('EmployeeWorkRecords', 'EmployeeWorkRecords'[EmployeeID], 'EmployeeWorkRecords'[Prichod], 'EmployeeWorkRecords'[Odchod]) ) VAR SortedParams = SORT(GroupParams, [ParallelParam], ASC) VAR CurrentRank = COUNTROWS(FILTER(SortedParams, [ParallelParam] <= CurrentParam)) RETURN CALCULATE( SUM('EmployeeWorkRecords'[TimeOfWork]), ALLEXCEPT('EmployeeWorkRecords', 'EmployeeWorkRecords'[EmployeeID], 'EmployeeWorkRecords'[Prichod], 'EmployeeWorkRecords'[Odchod]), FILTER(ALL('EmployeeWorkRecords'[ParallelParam]), 'EmployeeWorkRecords'[ParallelParam] <= CurrentParam) )
- 计算新的开始时间
NewPrichod:
NewPrichod = VAR TotalDuration = DATEDIFF('EmployeeWorkRecords'[Prichod], 'EmployeeWorkRecords'[Odchod], MINUTE) VAR PreviousCumulative = [CumulativeTime] - 'EmployeeWorkRecords'[TimeOfWork] RETURN 'EmployeeWorkRecords'[Prichod] + (PreviousCumulative / [TotalGroupTime]) * TotalDuration / 1440
- 计算新的结束时间
NewOdchod:
NewOdchod = VAR TotalDuration = DATEDIFF('EmployeeWorkRecords'[Prichod], 'EmployeeWorkRecords'[Odchod], MINUTE) RETURN 'EmployeeWorkRecords'[Prichod] + ([CumulativeTime] / [TotalGroupTime]) * TotalDuration / 1440
说明
- 两种方案均支持处理2个以上的并行任务;
- Power Query方案的优势是直接生成可导出的干净数据,适合其他系统使用;DAX方案则无需修改源数据,仅在报表层展示调整结果;
- 若并行参数不是合适的排序依据,可将代码中的
ParallelParam替换为JOBID或其他能区分任务顺序的字段。
内容的提问来源于stack exchange,提问作者CheliosSk
相关产品推荐
相关产品推荐

