如何将两个 Laravel Eloquent 查询合并为一个查询(所以我访问数据库一次而不是两次)

How to make two Laravel Eloquent queries into a single one (so I hit the database once instead of 2 times)

假设我的数据库中有 3 个 table。

'my_recipe'、'my_inventory' 和 'ingredient'。

'my_recipe' table 根据 'ingredient' table 和 'quantity' 的需要存储 raw_id 的列表食谱。 'my_inventory' table 存储 raw_id 和 'have_quantity'.

的列表

那么让我们来看看我目前拥有的东西。我有以下 2 个查询:

第一次查询:

$recipe = DB::table('my_recipe as tA')
    ->leftJoin('ingredient as tB', 'tA.raw_id', '=', 'tB.raw_id')
    ->select('tA.user as user', 'tA.raw_id as raw_id', 'tA.quantity as quantity',
        'tB.ingredient_name as ingredient_name')
    ->where('user', '=', $user)
    ->where('raw_id', '=', $raw_id)
    ->get();

第二次查询:

$inventory = DB::table('my_inventory as tA')
    ->leftJoin('ingredient as tB', 'tA.raw_id', '=', 'tB.raw_id')
    ->select('tA.user as user', 'tA.have_quantity as have_quantity',
        'tB.ingredient_name as ingredient_name')
    ->where('user', '=', $user)
    ->get();

第一个查询 returns 结果如下所示:

{"user":"jack","raw_id":"853","quantity":2,"ingredient_name":"apple"},
{"user":"jack","raw_id":"853","quantity":4,"ingredient_name":"peach"}

第二个查询 returns 结果如下所示:

{"user":"jack","have_quantity":30,"ingredient_name":"apple"},
{"user":"jack","have_quantity":20,"ingredient_name":"apple"},
{"user":"jack","have_quantity":10,"ingredient_name":"apple"},
{"user":"jack","have_quantity":1,"ingredient_name":"peach"},
{"user":"jack","have_quantity":1,"ingredient_name":"peach"}

请注意,在第二个查询结果中,我必须根据 'ingredient_name' 获得理想输出的成分总和。

如何在单个查询中获得理想的输出?

我理想的输出应该是这样的:

{"user":"jack","raw_id":"853","quantity":2,"ingredient_name":"apple","have_quantity":60},
{"user":"jack","raw_id":"853","quantity":4,"ingredient_name":"peach","have_quantity":2}

这基本上是第一个查询的结果加上第二个查询的总计 'have_quantity'。

编辑:

my_recipe 型号:

'user', 'raw_id', 'quantity'

my_inventory型号:

'user', 'raw_id', 'have_quantity'

成分型号:

'raw_id', 'ingredient_name'

注意:在配料模型中可以有相同 'ingredient_name' 但 'raw_id'.

不同的行

也许这可以解决你的问题

//replace count by sum
$inventory = DB::table('my_inventory as tA')
        ->leftJoin('ingredient as tB', 'tA.raw_id', '=', 'tB.raw_id')
        ->leftJoin('my_recipe as tC', 'tC.raw_id', '=', 'tB.raw_id')
        ->select(DB::raw('tA.user as user, tB.ingredient_name as ingredient_name, SUM(tA.have_quantity) have_quantity'))
        ->where('user', '=', $user)
        ->groupBy('tB.ingredient_name, tA.user')
        ->get();

根据我们的聊天对话,我设法获得了一些关于 table 结构的额外信息,以及需要做什么才能获得想要的结果。

感兴趣的人可以查看here

无论如何,我最终创建了这样的查询:

SELECT 
    my_recipe.user AS user,
    my_recipe.raw_id AS raw_id,
    my_recipe.quantity AS quantity,
    ingredient.ingredient_name AS ingredient_name,
    IFNULL(SUM(my_inventory.have_quantity),0) AS have_quantity
FROM my_recipe
LEFT JOIN ingredient USING(raw_id)
LEFT JOIN ingredient AS ingredients USING(ingredient_name)
LEFT JOIN my_inventory ON my_inventory.raw_id = ingredients.raw_id
WHERE my_recipe.recipe_id = 853 
AND my_recipe.user = 'jack'
AND my_inventory.user = 'jack'
GROUP BY ingredient_name;

现在转换成需要的结构:

$inventory = DB::table('my_recipe')
    ->leftJoin('ingredient', 'my_recipe.raw_id', '=', 'ingredient.raw_id')
    ->leftJoin('ingredient AS ingredients', 'ingredient.ingredient_name', '=', 'ingredients.ingredient_name')
    ->leftJoin('my_inventory', 'my_inventory.raw_id', '=', 'ingredients.raw_id')
    ->select(DB::raw('my_recipe.user AS user,my_recipe.raw_id AS raw_id,my_recipe.quantity AS quantity,ingredient.ingredient_name AS ingredient_name,IFNULL(SUM(my_inventory.have_quantity),0) AS have_quantity'))
    ->where('my_recipe.recipe_id', '=', $recipe_id)
    ->where('my_recipe.user', '=', $user)
    ->where('my_inventory.user', '=', $user)
    ->groupBy('ingredient_name')
    ->get();

让我们试试这个:

$result = DB::table('ingredient as ing')
    ->rightJoin('my_recipe as rcp', 'ing.raw_id', '=', 'rcp.raw_id')
    ->rightJoin('my_inventory as inv', 'ing.raw_id', '=', 'inv.raw_id')
    ->select(DB::raw('
        rcp.user as user, 
        ing.ingredient_name as ingredient_name, 
        rcp.have_quantity quantity, 
        SUM(inv.have_quantity) have_quantity
    '))
    ->where('rcp.user', '=', $user)
    ->where('rcp.raw_id', '=', $raw_id)
    ->groupBy('rcp.user, ing.ingredient_name')
    ->get();