【问题标题】:Grouped table causing sum() to multiple result分组表导致 sum() 到多个结果
【发布时间】:2018-01-07 19:25:34
【问题描述】:

也许只是因为太晚了,这可能是超级简单的事情,但我的查询有问题:

$lead = Lead::findOrFail($id);
$recipients = Recipient::with('segment')
    ->select('recipients.*',
        DB::raw('coalesce(rulesets.name, "Accept any...") as ruleset_name'),
        DB::raw('coalesce(sum(recipient_leads.leads_left), 0) as leads_left'),
        DB::raw('round(min('.((configuration('location_distance_unit') == 'km') ? '6371' : '3959').' * acos(cos(radians('.$lead->latitude.')) * cos(radians(recipient_locations.latitude)) * cos(radians(recipient_locations.longitude) - radians('.$lead->longitude.')) + sin(radians('.$lead->latitude.')) * sin(radians(recipient_locations.latitude))))) as distance'))
    ->leftJoin('rulesets', 'rulesets.id', '=', 'recipients.ruleset_id')
    ->leftJoin('recipient_leads', 'recipient_leads.recipient_id', '=', 'recipients.id')
    ->leftJoin('recipient_locations', 'recipient_locations.recipient_id', '=', 'recipients.id')
    ->where('recipients.segment_id', $lead->segment_id)
    ->where(function ($query) use ($lead) {
        $query->whereIn('recipients.ruleset_id', $lead->rulesetIds())->orWhereNull('recipients.ruleset_id');
    })
    ->whereRaw('distance <= recipient_locations.distance')
    ->where('recipients.active', true)
    ->where('leads_left', '>', 0)
    ->groupBy('recipients.id');

我的问题是 leads_left 的总和似乎乘以 recipient_locations 的数量。我尝试将recipient_locations.recipient_idrecipient_leads.recipient_id 添加到我的groupBy,但没有效果。

为什么会发生这种情况,我该如何解决?

编辑:这是原始查询:

select 
    `recipients`.*, 
    coalesce(rulesets.name, "Accept any...") as ruleset_name, 
    coalesce(sum(recipient_leads.leads_left), 0) as leads_left, 
    round(min(6371 * acos(cos(radians(43.8988057)) * cos(radians(recipient_locations.latitude)) * cos(radians(recipient_locations.longitude) - radians(-78.6974833)) + sin(radians(43.8988057)) * sin(radians(recipient_locations.latitude))))) as distance 
from `recipients` 
left join `rulesets` on `rulesets`.`id` = `recipients`.`ruleset_id` 
left join `recipient_leads` on `recipient_leads`.`recipient_id` = `recipients`.`id` 
left join `recipient_locations` on `recipient_locations`.`recipient_id` = `recipients`.`id` 
where `recipients`.`segment_id` = ? and (`recipients`.`ruleset_id` in (?, ?) or `recipients`.`ruleset_id` is null) and distance <= recipient_locations.distance and `recipients`.`active` = ? and `leads_left` > ? 
group by `recipients`.`id`

【问题讨论】:

  • 尝试使用 where
  • 是多对多关系吗,可能是笛卡尔积
  • 这是雄辩的?我讨厌查询构建器,它们丑陋且难以优化查询。
  • 我需要使用haversine公式查询。我必须使用查询生成器。我只想知道为什么它不应该乘以leads_left的总和。
  • 我已将实际的 SQL 查询添加到 OP。

标签: php mysql laravel


【解决方案1】:

所以我不会尝试重写整个查询,但您的问题是,当您使用多个这样的左连接时,左侧的匹配行会在右侧重复(这就是为什么您的总和是错了)。

如果您在连接之前计算sum,它应该会按照您想要的方式工作。

其实这里有一个之前的回答很好的解释了:

Using SUM with multiple joins in mysql

【讨论】:

  • 在连接完美之前计算总和。例如。 (select coalesce(sum(leads_left), 0) from recipient_leads where recipient_id=recipients.id) as leads_left
  • 很高兴知道这解决了您的问题,几周前我遇到了类似的问题,并记得上面的帖子:)
猜你喜欢
  • 2013-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多