You need to enable JavaScript to run this app. Laravel 股票事务聚合查询:如何不按bought字段分组实现正确统计
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.29 17:45:10