Laravel 股票事务聚合查询:如何不按bought字段分组实现正确统计
修正思路
之前的逻辑把bought字段加入分组维度,导致同一只股票的买入、卖出交易被拆成两行统计。解决方法很简单:把买卖类型的判断嵌入聚合计算过程,完全不需要把bought纳入分组条件。
关键调整内容
- 从
groupBy中移除bought,仅保留name、symbol、currency三个分组维度 - 调整
CASE的判断位置:不再在分组后判断整组的交易类型,而是把判断逻辑放到SUM函数内部,逐行判断当前交易的类型,累加对应金额即可 - 修正原有计算的bug:原来写的
sum(price) * sum(amount_bought)在多笔不同价格买入的场景下会算错,正确逻辑应该是逐行计算单价*交易数量后再累加 - 加空值保护:用
COALESCE把交易表中为NULL的买入/卖出数量转成0,避免SUM计算出现偏差
修正后的查询代码
$transactions = Transaction::where('portfolio_id', $portfolio->id) ->groupBy('name', 'symbol', 'currency') ->select([ 'name', 'symbol', 'currency', // 当前持仓数量:总买入量 - 总卖出量 DB::raw('SUM(COALESCE(amount_bought, 0)) - SUM(COALESCE(amount_sold, 0)) as amount_current'), // 累计交易佣金总和 DB::raw('SUM(commission) AS commission_total'), // 累计买入总支出:仅统计bought=1的交易的成交金额 DB::raw('SUM(CASE WHEN bought = 1 THEN price * amount_bought ELSE 0 END) as bought_total'), // 累计卖出总收入:仅统计bought=0的交易的成交金额 DB::raw('SUM(CASE WHEN bought = 0 THEN price * amount_sold ELSE 0 END) as sales_total') ]) ->get();
测试数据匹配验证
用你提供的3条交易数据计算,结果和预期完全一致:
- Ocugen Inc 行:持仓15股、总佣金15.06、买入总支出15.95、卖出总收入52.4
- Tesla, Inc 行:持仓5股、总佣金4.23、买入总支出3274.35、卖出总收入0
内容的提问来源于stack exchange,提问作者Tomjesch
相关产品推荐
相关产品推荐

