Php 对子表中的相关行进行计数

Php 对子表中的相关行进行计数,php,mysql,sql,laravel,eloquent,Php,Mysql,Sql,Laravel,Eloquent,我一直在尝试使用eloquent进行一些查询,并对相关表进行计数 表: 请求 联系人属于请求 历史属于接触 因此,X数量的请求每个都有Y数量的联系人,每个联系人都有Z数量的历史记录 使用sql,我可以这样做来获取所有计数 SELECT id, ( SELECT count(contact.id) FROM contact WHERE contact.requests_id = requests.id ) AS n_c

我一直在尝试使用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;
但是,当使用Elount构建查询时,我有点不知所措。例如,如果我正在为给定的请求选择所有联系人,我将在什么时候加入/统计历史记录?或者我需要在这3个表的相关模型中添加一些访问器吗

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

提前感谢您提供的帮助。

如果您想使用Eloquent而不是手动连接,您可以使用helper relation:

// 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;
}
从接触模型到历史模型也是如此

对于计算远端关系请求->历史记录,您可以使用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

你想每Y数Z,每X数Y,每X数Z还是什么?我想得到每X数Z,每Y数Z。所以给定一个特定的Z或X,我可以得到一个Y数。