计算子表中的相关行

时间:2014-07-25 13:59:03

标签: php mysql sql laravel eloquent

我一直在努力做一些查询,并使用雄辩的方法来计算相关的表。

表:

  • 请求
  • 联系(属于请求)
  • 历史(属于联系方式)

因此,X个请求每个都有Y个联系人,其中每个联系人都有Z个历史记录

使用sql我可以做这样的事情来获得所有的计数。

SELECT
    id,
    (
         SELECT count(contact.id)
         FROM contact 
         WHERE contact.requests_id = requests.id
    ) AS n_contact,
    (
         SELECT count(history.id)
         FROM contact INNER JOIN history ON (history.contact_id = contact.id)
         WHERE contact.requests_id = requests.id
    ) AS n_history
FROM requests;

Above Query

但是在使用eloquent构建查询时我有点迷失。例如,如果我选择了给定请求的所有联系人,我将在何时加入/计算历史记录?或者我是否需要在这些3个表的相关模型中添加一些访问器?

public function getAllContacts($id) {
    return Requests::where('requests.id', '=', $id)
            ->join('requests', 'contact.requests_id', '=', 'requests.id')
            ->select('contact.*', 'requests.name');
            ->get();
}

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

如果您想使用Eloquent而不是手动连接,可以使用帮助关系:

// Request model
public function contactsCount()
{
    return $this->hasOne('Contact')->selectRaw('request_id, count(*) as aggregate')->groupBy('request_id');
}

public function getContactsCountAttribute()
{
    if ( ! array_key_exists('contactsCount', $this->relations)) $this->load('contactsCount');

    return $this->getRelation('contactsCount')->aggregate;
}

同样适用于Contact模型的History模型。

为了计算远距离关系(Request - > History),您可以使用hasManyThrough关系进行一点调整。

通过这种方式,您可以在没有n + 1问题的情况下为多个模型急切加载这些聚合,非常简单:

$requests = Request::with('contactsCount', 'contacts.historyCount')->get();
// 1 query for reuqests, 1 query for contacts count and 2 queries for contacts.historyCount

// example output
$requests->first()->contactsCount; // 17
$requests->first()->contacts->first()->historyCount; // 5