PHP MySQL PDO计算动量指标时出现异常循环与数据重复问题
问题排查与修复建议
先直接点出核心问题:你的重复数据是因为循环逻辑错误,每新增一条CSV数据,就会重新遍历所有满足i>=14的位置并重复插入,导致数据条数随记录数递增式重复。另外还有变量绑定、数组初始化的问题,下面一步步拆解:
1. 核心循环逻辑错误
你在foreach ($sql as $data)循环里,每次都执行$close[] = $data['Close'];把当前收盘价加入数组,然后立刻用for($i=14;$i<$jumlah;$i++)遍历整个数组从第14位到末尾,这意味着:
- 当处理第15条CSV数据时,
$jumlah=15,i从14开始,插入1条数据 - 处理第16条时,
$jumlah=16,i从14到15,插入2条重复的(对应第15、16条的动量,但其实第15条的动量已经在上一次循环插入过了) - 以此类推,每多一条数据,就多插入N条重复项,完全不符合“每条数据对应一条动量记录”的需求
正确的逻辑应该是:先收集所有收盘价和日期到数组,再从第15条数据(数组索引从0开始的话是索引14)开始,逐个计算并插入对应动量值,而不是每次循环都重新遍历整个数组。
2. 变量绑定与字段对应错误
你的bindParam完全搞反了字段和变量的对应关系:
:close14应该绑定的是14天前的收盘价$close1,而不是整个$close数组:close应该绑定当前的收盘价,而不是14天前的价格- 另外,
bindParam是引用传递,在循环里容易出现变量覆盖问题,建议直接用execute的参数数组更安全
3. 冗余的PDO连接
你分别为查询和插入创建了两个PDO连接,这不仅浪费资源,还可能导致事务一致性问题,应该复用同一个连接。
修复后的完整代码
// 只创建一次PDO连接,复用整个流程 $conn = new PDO('mysql:host='.$host.';dbname='.$database, $username, $password); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 1. 先查询所有CSV数据,按日期排序 $stmt = $conn->prepare("SELECT Date, Close FROM csv_data ORDER BY Date"); $stmt->execute(); $allData = $stmt->fetchAll(PDO::FETCH_ASSOC); // 2. 分离日期和收盘价到独立数组,方便后续索引调用 $dates = []; $closes = []; foreach ($allData as $data) { $dates[] = $data['Date']; $closes[] = $data['Close']; } // 3. 提前准备插入语句(只需要准备一次) $insertStmt = $conn->prepare("INSERT INTO momentum_data (Date, Close, Close14, Momentum) VALUES (:Date, :close, :close14, :momentum)"); // 4. 从第15条数据开始计算动量(数组索引从0开始,i从14起对应第15条) $totalRecords = count($closes); for ($i = 14; $i < $totalRecords; $i++) { $currentDate = $dates[$i]; $currentClose = $closes[$i]; $close14DaysAgo = $closes[$i - 14]; // 按你原公式计算动量 $momentum = ($currentClose / $close14DaysAgo) * 100; // 直接传递参数数组执行插入,避免引用传递的坑 $insertStmt->execute([ ':Date' => $currentDate, ':close' => $currentClose, ':close14' => $close14DaysAgo, ':momentum' => $momentum ]); }
额外优化建议
- 如果你的CSV数据量很大,建议用事务包裹插入操作,提升性能并保证数据一致性:
$conn->beginTransaction(); // 插入循环代码... $conn->commit(); - 可以给
momentum_data表的Date字段加唯一索引,防止意外重复插入(如果日期是唯一标识的话) - 计算动量时注意除数为0的情况(如果14天前的收盘价是0,需要做异常处理)
内容的提问来源于stack exchange,提问作者stephenkim
相关产品推荐
相关产品推荐

