如何从MySQL表按WORK_ID提取连续日期对用于计算工作日差
解决方法:提取分组内的连续日期对
针对你的需求,因为数据表数据量很大,优先推荐用SQL直接提取日期对,比先把所有数据拉到PHP里处理高效得多。下面分两种场景给出方案:
一、用SQL(推荐,适合大数据量)
如果你的数据库支持窗口函数(比如MySQL 8.0+、PostgreSQL、SQL Server等),可以用LAG()函数来获取每组内的上一个日期,直接生成需要的日期对:
SELECT WORK_ID, DATE AS current_date, LAG(DATE) OVER (PARTITION BY WORK_ID ORDER BY DATE ASC) AS prev_date, ROW_NUMBER() OVER (PARTITION BY WORK_ID ORDER BY DATE DESC) AS pair_number FROM Work WHERE LAG(DATE) OVER (PARTITION BY WORK_ID ORDER BY DATE ASC) IS NOT NULL ORDER BY WORK_ID ASC, pair_number ASC;
说明:
PARTITION BY WORK_ID:按工作ID分组处理数据ORDER BY DATE ASC:每组内按日期升序排列,LAG(DATE)就能拿到当前日期的前一个更早日期ROW_NUMBER() OVER (...) AS pair_number:给每组内的日期对编号,按日期降序排序后,最新的日期对就是Pair 1,和你要的输出格式完全匹配WHERE ... IS NOT NULL:过滤掉每组的第一个日期(它没有前一个日期,无法形成有效配对)
执行这个SQL后,你会得到结构化的结果集,接着在PHP里遍历即可输出目标格式,同时调用你的工作日计算函数:
// 假设$pdo是你的数据库连接实例 $sql = "上述SQL语句"; $stmt = $pdo->query($sql); while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { $datePair = "{$row['current_date']} - {$row['prev_date']} (Pair {$row['pair_number']} of work_id {$row['WORK_ID']})"; echo $datePair . PHP_EOL; // 调用你的工作日计算函数 $workDays = kac_is_gunu($row['current_date'], $row['prev_date']); // 这里可以根据需求存储或输出计算结果 }
二、PHP处理(适合不支持窗口函数的旧数据库)
如果你的数据库不支持窗口函数,只能先把数据按WORK_ID分组查询出来,再在PHP里处理:
步骤1:查询并分组数据
$sql = "SELECT WORK_ID, DATE FROM Work ORDER BY WORK_ID ASC, DATE ASC"; $stmt = $pdo->query($sql); $workDates = []; while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { $workId = $row['WORK_ID']; if (!isset($workDates[$workId])) { $workDates[$workId] = []; } $workDates[$workId][] = $row['DATE']; }
步骤2:遍历分组生成日期对
foreach ($workDates as $workId => $dates) { $pairCount = count($dates) - 1; // 每组的配对数等于日期总数减1 // 从后往前遍历,生成符合要求的配对编号 for ($i = $pairCount; $i > 0; $i--) { $currentDate = $dates[$i]; $prevDate = $dates[$i-1]; $pairNumber = $pairCount - $i + 1; // 最新的配对编号为1 echo "{$currentDate} - {$prevDate} (Pair {$pairNumber} of work_id {$workId})" . PHP_EOL; // 调用计算函数 $workDays = kac_is_gunu($currentDate, $prevDate); // 处理计算结果 } }
注意:
这种方法需要把所有数据加载到PHP内存中,如果数据量特别大(比如百万级以上),可能会出现内存溢出问题,所以还是优先选择SQL窗口函数的方案。
最终输出示例
不管用哪种方法,最终输出都会和你期望的格式一致:
2018-05-16 - 2018-05-15 (Pair 1 of work_id 5) 2018-05-15 - 2018-05-10 (Pair 2 of work_id 5) 2018-05-16 - 2018-05-12 (Pair 1 of work_id 6)
内容的提问来源于stack exchange,提问作者TahaG
相关产品推荐
相关产品推荐

