已解决,使用 withCount 关联统计报错:SQLSTATE[42S22]: Column not found: 1054 Unknown column

环境:本地 windows + 小皮 phpstudy

框架:基于 Thinkphp5.0 的 Fastadmin

PHP 版本:7.4.3

场景及代码描述:

我在开发一个外卖订单分析系统,有一个需求是对骑手订单量进行一个排行,表结构大致如下:

`knight` 骑手表:id、knight_local_code...
`orders` 订单表:id、knight_local_code...

骑手表与订单表是一对多的关系,我需要查询骑手数据并关联订单表的数据,代码如下:

knight模型:

public function orders()
{
    return $this->hasMany('app\admin\model\Orders', 'knight_local_code', 'knight_local_code');
}

knight控制器:

public function index()
{
    //当前是否为关联查询
    $this->relationSearch = true;
    //设置过滤方法
    $this->request->filter(['strip_tags', 'trim']);
    if ($this->request->isAjax()) {
        //如果发送的来源是Selectpage,则转发到Selectpage
        if ($this->request->request('keyField')) {
            return $this->selectpage();
        }
        list($where, $sort, $order, $offset, $limit) = $this->buildparams();
        $list = $this->model
            ->with(['team', 'type'])
            ->withCount('orders')
            ->where($where)
            ->order($sort, $order)
            ->paginate($limit);

        foreach ($list as $row) {
            $row->getRelation('team')->visible(['name']);
            $row->getRelation('type')->visible(['name']);
        }

        $result = array("total" => $list->total(), "rows" => $list->items());

        return json($result);
    }
    return $this->view->fetch();
}

问题描述:

我使用 withCount 进行关联统计查询,会报以下错,但根据错误描述,实际上fa_knight表中的knight_local_code字段是存在的

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'fa_knight.knight_local_code' in 'where clause'

使用 withCount 关联统计报错:SQLSTATE[42S22]: Column not found: 1054 Unknown column

使用 withCount 关联统计报错:SQLSTATE[42S22]: Column not found: 1054 Unknown column

换个思路

于是为了排查是不是未知列的错误,我换了一种方式进行查询:
knight模型代码不变,我将knight控制器的代码修改成with关联,先不使用withcount,然后在foreach里面去count()查询订单数量,此时查询结果是正常的:

knight控制器:

public function index()
{
    //当前是否为关联查询
    $this->relationSearch = true;
    //设置过滤方法
    $this->request->filter(['strip_tags', 'trim']);
    if ($this->request->isAjax()) {
        //如果发送的来源是Selectpage,则转发到Selectpage
        if ($this->request->request('keyField')) {
            return $this->selectpage();
        }
        list($where, $sort, $order, $offset, $limit) = $this->buildparams();
        $list = $this->model
            ->with(['team', 'type', 'orders'])
            ->where($where)
            ->order($sort, $order)
            ->paginate($limit);

        foreach ($list as $row) {
            $row->getRelation('team')->visible(['name']);
            $row->getRelation('type')->visible(['name']);
            $row['orders_count'] = count($row->orders);
        }

        $result = array("total" => $list->total(), "rows" => $list->items());

        return json($result);
    }
    return $this->view->fetch();
}

使用 withCount 关联统计报错:SQLSTATE[42S22]: Column not found: 1054 Unknown column

请各位大佬帮忙看下是什么原因,十分感谢!

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
最佳答案

/thinkphp/library/think/model/relation/HasMany.php 文件中修改 getRelationCountQuery 方法:

public function getRelationCountQuery($closure, &$name = null)
{
    if ($closure) {
        $return = call_user_func_array($closure, [ & $this->query]);
        if ($return && is_string($return)) {
            $name = $return;
        }
    }
    $localKey = $this->localKey ?: $this->parent->getPk();
    $parentTable = $this->parent->getTable();
    $options = $this->parent->getOptions();
    if(isset($options['alias'][$parentTable])){
        $parentTable = $options['alias'][$parentTable];
    }
    return $this->query->whereExp($this->foreignKey, '=' . $parentTable . '.' . $localKey)->fetchSql()->count();
}

修改后的方法通过 $this->parent->getTable() 获取了父模型的表名,并通过 $options['alias'] 获取了可能存在的表名别名,在构建关联关系的查询条件时,考虑到了表名别名的情况

1年前 评论
巴啦啦臭魔仙 (作者) (楼主) 1年前
讨论数量: 3

/thinkphp/library/think/model/relation/HasMany.php 文件中修改 getRelationCountQuery 方法:

public function getRelationCountQuery($closure, &$name = null)
{
    if ($closure) {
        $return = call_user_func_array($closure, [ & $this->query]);
        if ($return && is_string($return)) {
            $name = $return;
        }
    }
    $localKey = $this->localKey ?: $this->parent->getPk();
    $parentTable = $this->parent->getTable();
    $options = $this->parent->getOptions();
    if(isset($options['alias'][$parentTable])){
        $parentTable = $options['alias'][$parentTable];
    }
    return $this->query->whereExp($this->foreignKey, '=' . $parentTable . '.' . $localKey)->fetchSql()->count();
}

修改后的方法通过 $this->parent->getTable() 获取了父模型的表名,并通过 $options['alias'] 获取了可能存在的表名别名,在构建关联关系的查询条件时,考虑到了表名别名的情况

1年前 评论
巴啦啦臭魔仙 (作者) (楼主) 1年前

或者不使用子查询方式:

->withCount('orders', false)
1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!