从关系集合中返回包含SUM和COUNT的特定列

时间:2018-11-02 13:44:02

标签: laravel eloquent

我有模型ProductProductVariantDepartment

部门:

id | name | ....

产品:

id | name | sku | department_id | ....

ProductVariant:

id | product_id | quantity | ....

所有彼此关联的事物,例如:

  • 关系products:部门hasMany产品
  • 关系department:产品belongsTo部门
  • 关系variants:产品hasMany ProductVariants
  • 关系product:产品belongsTo产品

一切事情在雄辩的通话之间都能按预期进行

现在,我使用雄辩的方法尝试检索以下各列的集合:

product.id | product.name | product.variant_count | product.stock | department.name

我所说的product.stock$product->variants->sum('quantity'),但是我很难在SUM方法中使用with()

到目前为止,我已经尝试过:

      $products = Product::select('id', 'name', 'sku', 'department_id') //gives product.name, sku, etc
            ->withCount('variants')                    //gives product.variants_count
            ->with(['variants' => function($query) {
                $query->select('id', 'product_id', 'quantity'); //gives variants->each.quantity
            }])
            ->with(['department' => function($query) {
                $query->select('id', 'name');              //gives department.name
            }]);

这段代码给出了这样的内容:

[
{
    "id": "2",
    "name": "Letv LU50609 Earphone - Grey",
    "sku": "PT-00002",
    "department_id": "2",
    "variants_count": "1",
    "variants": [
        {
            "id": "2",
            "product_id": "2",
            "quantity": "35"
        }
    ],
    "department": {
        "id": "2",
        "name": "Phones & Tabs Accessories"
    }
},
{
    "id": "3",
    "name": "MI In-Ear Headphones Basic 3.5mm HSEJ03JY",
    "sku": "PT-00003",
    "department_id": "2",
    "variants_count": "5",
    "variants": [
        {
            "id": "3",
            "product_id": "3",
            "quantity": "9"
        },
        {
            "id": "4",
            "product_id": "3",
            "quantity": "9"
        },
        {
            "id": "5",
            "product_id": "3",
            "quantity": "10"
        },
        {
            "id": "6",
            "product_id": "3",
            "quantity": "7"
        },
        {
            "id": "7",
            "product_id": "3",
            "quantity": "7"
        }
    ],
    "department": {
        "id": "2",
        "name": "Phones & Tabs Accessories"
    }
}
]

但是我想要实现的是:

[
{
    "id": "2",
    "name": "Letv LU50609 Earphone - Grey",
    "sku": "PT-00002",
    "variants_count": "1",
    "stock": "35",
    "department": "name": "Phones & Tabs Accessories"
},
{
    "id": "3",
    "name": "MI In-Ear Headphones Basic 3.5mm HSEJ03JY",
    "sku": "PT-00003",
    "variants_count": "5",
    "stock": "42",
    "department": "name": "Phones & Tabs Accessories"
}
]

我该如何实现??

4 个答案:

答案 0 :(得分:1)

使用这样的查询生成器怎么样:

DB::table('products as product')
   ->select([
        'product.id',
        'product.name',
         DB::raw('count(pv.id) as variant_count'),
         DB::raw('sum(pv.quantity) as stock'),
        'department.name'
   ])
   ->join('department', 'product.department_id', '=', 'department.id')
   ->join('product_variants as pv', 'product.id', '=', 'pv.id')
   ->get();

不确定这是否会像这样正常工作,但应该为您提供一条路径。

答案 1 :(得分:1)

选项1

您可以map()收集收藏集,然后将其退回:

  $products = Product::select('id', 'name', 'sku', 'department_id')
        ->withCount('variants')
        ->with(['variants', 'department'])
        ->get()
        ->map(function ($product){
                return [
                    'id'             => $product->id,
                    'name'           => $product->name,
                    'sku'            => $product->sku,
                    'variants_count' => $product->variants_count,
                    'stock'          => $product->variants->sum('quantity'),
                    'department'     => $product->department->name
                ];
            });

选项2

使用API Resources。让我知道您是否需要这方面的帮助。

答案 2 :(得分:0)

您可以通过查询数据库表

来访问此查询所需的结果
 SELECT
    products.*,
    SUM(variants.available) AS stock,
    COUNT(variants.id)  as count,
    department.name as department
FROM
    products
LEFT JOIN variants ON products.id = variants.product_id
LEFT JOIN department ON products.department_id= department.id
GROUP BY
    products.id

答案 3 :(得分:0)

您正在寻找的东西可以通过多种方式实现。理想的解决方案将在数据库中构建总和以获得最佳性能。为此,您可以将自定义查询与Laravel查询构建器一起使用,如@nakov所解释的那样,或者您可以使用Eloquent关系系统的一些漏洞利用方法:

$products = Product::query()
    ->join('departments', 'departments.id', '=', 'products.department_id)
    ->withCount('variants as variant_count')
    ->withCount(['variants as stock' => function ($query) {
        $query->selectRaw('SUM(quantity)');  // this may look weird but works
    })
    ->select([
        'products.id',
        'products.name',
        'departments.name as department',
    ])
    ->get();