You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Power BI中如何筛选并调整并行工作时间数据行

解决方案:处理Power BI中的并行工作记录时间拆分

针对你遇到的并行工作记录(起止时间相同、仅TimeOfWork和并行参数不同)的时间调整需求,以下提供两种可行方案,均无需修改原系统的输入输出:


方案一:Power Query预处理数据(推荐,适合导出至其他系统)

通过Power Query批量转换数据,直接生成调整后的起止时间,处理后的数据可直接导出给其他系统,不会被识别为重复项。

步骤&代码示例

假设你的数据表名为EmployeeWorkRecords,包含列:EmployeeID、Prichod(开始时间)、Odchod(结束时间)、JOBID、ParallelParam(并行参数)、TimeOfWork(工作时长,单位:分钟)

  1. 进入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
  1. 运行查询后,即可得到调整后的记录:并行任务的起止时间会按TimeOfWork的占比依次拆分,不会再出现重复的时间区间。

方案二:DAX计算列(适合Power BI报表内展示)

如果仅需在Power BI报表中展示调整后的时间,无需修改源数据,可通过DAX创建计算列实现:

计算列代码

  1. 计算同一员工、同一时间组的总工作时长:
TotalGroupTime = 
CALCULATE(
    SUM('EmployeeWorkRecords'[TimeOfWork]),
    ALLEXCEPT('EmployeeWorkRecords', 'EmployeeWorkRecords'[EmployeeID], 'EmployeeWorkRecords'[Prichod], 'EmployeeWorkRecords'[Odchod])
)
  1. 计算当前行在组内的累计工作时长(按并行参数排序):
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)
)
  1. 计算新的开始时间NewPrichod:
NewPrichod = 
VAR TotalDuration = DATEDIFF('EmployeeWorkRecords'[Prichod], 'EmployeeWorkRecords'[Odchod], MINUTE)
VAR PreviousCumulative = [CumulativeTime] - 'EmployeeWorkRecords'[TimeOfWork]
RETURN
'EmployeeWorkRecords'[Prichod] + (PreviousCumulative / [TotalGroupTime]) * TotalDuration / 1440
  1. 计算新的结束时间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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 10:12:54