如何用单条查询实现一对多计数?(基于Lumen v5.6.1)
获取每个Set对应的关联Indexed Items计数(Lumen 5.6.1)
没问题呀,隔段时间没碰后端难免会有点生疏,这问题一点都不基础,是很常见的关联统计需求~我帮你梳理下两种常用的实现方式,适配你用的Lumen 5.6.1:
1. 原生SQL查询(直观易懂)
先从最基础的SQL开始,这样能清晰理解逻辑:
SELECT s.ID, s.`SET`, COUNT(ii.id) AS item_count FROM `table.sets` s LEFT JOIN `table.indexed_items` ii ON s.ID = ii.setId GROUP BY s.ID, s.`SET`
- 用
LEFT JOIN是为了保留所有Set记录,哪怕某个Set没有对应的Indexed Items,此时计数会显示为0; - 用
COUNT(ii.id)而不是COUNT(*),因为LEFT JOIN后无关联的记录中ii.id为NULL,COUNT会自动忽略NULL值,确保计数准确。
2. Lumen Eloquent 实现(推荐,更优雅)
如果已经定义了Eloquent模型,用框架自带的withCount方法是最便捷的:
首先定义模型
Set模型(app/Set.php)
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Set extends Model { protected $table = 'table.sets'; protected $primaryKey = 'ID'; public $timestamps = false; // 如果表中没有created_at/updated_at字段,需要设置这个 // 定义与IndexedItem的关联 public function indexedItems() { return $this->hasMany(IndexedItem::class, 'setId', 'ID'); } }
IndexedItem模型(app/IndexedItem.php)
<?php namespace App; use Illuminate\Database\Eloquent\Model; class IndexedItem extends Model { protected $table = 'table.indexed_items'; protected $primaryKey = 'ID'; public $timestamps = false; }
执行查询
// 获取所有Set及其关联记录数 $sets = \App\Set::withCount('indexedItems')->get(); // 遍历结果示例 foreach ($sets as $set) { echo "Set ID: {$set->ID} | 名称: {$set->SET} | 关联记录数: {$set->indexed_items_count}\n"; }
withCount会自动帮你生成对应的左连接和分组统计SQL,代码简洁且符合Laravel/Lumen的最佳实践。
3. Lumen DB门面实现(无需模型)
如果不想定义模型,直接用DB门面执行原生查询:
$results = \Illuminate\Support\Facades\DB::table('table.sets as s') ->leftJoin('table.indexed_items as ii', 's.ID', '=', 'ii.setId') ->select( 's.ID', 's.SET', \Illuminate\Support\Facades\DB::raw('COUNT(ii.id) as item_count') ) ->groupBy('s.ID', 's.SET') ->get(); // 遍历结果示例 foreach ($results as $row) { echo "Set ID: {$row->ID} | 名称: {$row->SET} | 关联记录数: {$row->item_count}\n"; }
这里用DB::raw()来包裹COUNT表达式,避免框架对SQL片段进行不必要的转义。
内容的提问来源于stack exchange,提问作者Caleb Nance
相关产品推荐
相关产品推荐

