如何通过在Laravel中分组库存单位找到最畅销的商品?

时间:2019-01-16 19:48:03

标签: php laravel laravel-5 pdo eloquent

我正在尝试根据在该产品上创建了多少库存单位来选择最畅销的产品。产品上的库存单位越多=销售量越多。

我的product_list表如下:

Schema::create('product_list', function (Blueprint $table) {
    $table->increments('id');
    $table->decimal('cost', 9, 2)->default(00.00);
    $table->integer('product_category')->unsigned();            # IE Bespoke/Static/Dynamic
    $table->integer('product_type')->unsigned();                # IE Themes(Custom Or Not)/Number of pages
    $table->integer('product_score')->default(0);               # How many favourites does it have?
    $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
    $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));

    $table->index(array('product_category', 'product_type'));

    $table->foreign('product_category')->references('id')->on('product_categories');
    $table->foreign('product_type')->references('id')->on('product_types')->onDelete('cascade');
    });

我的products_skus表如下:

Schema::create('product_skus', function (Blueprint $table) {
    $table->increments('id');
    $table->string('reference');
    $table->integer('product_id')->unsigned();
    $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
    $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));

    $table->index(array('product_id'));

    $table->foreign('product_id')->references('id')->on('product_list')->onDelete('cascade');
});

这是我到目前为止使用Eloquent尝试的方法-不必太在意现在加入任何其他联接,只是让最畅销的产品起作用:

$topSellers = DB::table('product_list')->join('product_skus', 'product_skus.product_id', '=', 'product_list.id')
                                       ->groupBy('product_skus.product_id')
                                       ->limit(5)
                                       ->get()
                                       ->all();

哪个给我这个错误:

  

SQLSTATE [42000]:语法错误或访问冲突:1055'iezonsolutions.product_list.id'不在GROUP BY(42000)中

如何找到最畅销的商品?我会在每一个product_item售出时为它创建一个SKU,这是跟踪畅销商品的一种方式,并且为用户提供了独特的跟踪能力。

更新以显示关系

product_skus具有与product_id表列product_list相关的外键id。我想根据产品ID的关系对库存单位进行分组。将最多SKU归类到该单个产品ID,我想从product_list表中获取产品

$topSellers = DB::table('product_skus')->join('product_list', 'product_skus.product_id', '=', 'product_list.id')
                                       ->orderBy('product_skus.product_id')
                                       ->limit(5)
                                       ->get()
                                       ->all();

现在正在对正确的关系进行分组,但是,它给了我

的输出
array:3 [▼
  0 => {#725 ▼
    +"id": 2
    +"reference": "A400IEZON_"
    +"product_id": 2
    +"created_at": "2019-01-16 16:37:16"
    +"updated_at": "2019-01-16 16:37:16"
    +"cost": "100.00"
    +"product_category": 1
    +"product_type": 2
    +"product_score": 0
    +"rating": 0
    +"down_payment": "10.00"
  }
  1 => {#726 ▼
    +"id": 3
    +"reference": "C400IEZON_"
    +"product_id": 3
    +"created_at": "2019-01-16 16:37:25"
    +"updated_at": "2019-01-16 16:37:25"
    +"cost": "150.00"
    +"product_category": 1
    +"product_type": 3
    +"product_score": 0
    +"rating": 0
    +"down_payment": "10.00"
  }
  2 => {#727 ▼
    +"id": 3
    +"reference": "C400IEZON_"
    +"product_id": 3
    +"created_at": "2019-01-16 16:37:25"
    +"updated_at": "2019-01-16 16:37:25"
    +"cost": "150.00"
    +"product_category": 1
    +"product_type": 3
    +"product_score": 0
    +"rating": 0
    +"down_payment": "10.00"
  }
]

我想将所有这些都计算在内,因此在这里,带有id 3的产品应显示为顶级产品,然后是产品2。

1 个答案:

答案 0 :(得分:1)

您可以使用子查询来实现。

$skus = ProductSku::selectRaw('COUNT(*)')
    ->whereColumn('product_id', 'product_list.id')
    ->getQuery();

$products = ProductList::select('*')
    ->selectSub($skus, 'skus_count')
    ->orderBy('skus_count', 'DESC')
    ->take(5)
    ->get();

如果ProductListProductSku有关系,这会容易得多。 然后,您可以这样做:

例如,在App\ProductList中,您可能会遇到类似这样的情况:

public function skus()
{
    return $this->hasMany(ProductSku::class);
}

..然后,您的查询就是:

ProductList::withCount('skus') 
    ->orderBy('skus_count', 'DESC')
    ->take(5)
    ->get();

..将产生与上面相同的查询。我不确定您的型号名称。您应该相应地对其进行更改。