Php 如何将两个Laravel雄辩的查询转换为一个查询(因此我只访问了数据库一次,而不是两次)

Php 如何将两个Laravel雄辩的查询转换为一个查询(因此我只访问了数据库一次,而不是两次),php,mysql,laravel,eloquent,laravel-query-builder,Php,Mysql,Laravel,Eloquent,Laravel Query Builder,假设我的数据库中有3个表 “我的食谱”、“我的清单”和“配料” “我的配方”表根据“配料”表和配方的“数量”需求存储原始id列表。“my_inventory”表存储原始id和“have_quantity”的列表 所以让我们看看我目前所拥有的东西。我有以下两个问题: 第一个问题: $recipe = DB::table('my_recipe as tA') ->leftJoin('ingredient as tB', 'tA.raw_id', '=', 'tB.raw_id')

假设我的数据库中有3个表

“我的食谱”、“我的清单”和“配料”

“我的配方”表根据“配料”表和配方的“数量”需求存储原始id列表。“my_inventory”表存储原始id和“have_quantity”的列表

所以让我们看看我目前所拥有的东西。我有以下两个问题:

第一个问题:

$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();
第一个查询返回的结果如下所示:

{"user":"jack","raw_id":"853","quantity":2,"ingredient_name":"apple"},
{"user":"jack","raw_id":"853","quantity":4,"ingredient_name":"peach"}
{"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"}
{"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}
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;
第二个查询返回如下结果:

{"user":"jack","raw_id":"853","quantity":2,"ingredient_name":"apple"},
{"user":"jack","raw_id":"853","quantity":4,"ingredient_name":"peach"}
{"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"}
{"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}
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;
注意,在第二个查询结果中,我必须根据理想输出的“成分名称”获得成分的总和

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

我的理想输出如下所示:

{"user":"jack","raw_id":"853","quantity":2,"ingredient_name":"apple"},
{"user":"jack","raw_id":"853","quantity":4,"ingredient_name":"peach"}
{"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"}
{"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}
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;
它基本上是第一次查询的结果,包含第二次查询的“have_quantity”总计

编辑:

我的食谱模型:

'user', 'raw_id', 'quantity'
我的库存模型:

'user', 'raw_id', 'have_quantity'
成分模型:

'raw_id', 'ingredient_name'

注意:在配料模型中,可以有具有相同“配料名称”但具有不同“原始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();

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

对于那些感兴趣的人,可以找到这些信息

无论如何,我最终创建了如下查询:

{"user":"jack","raw_id":"853","quantity":2,"ingredient_name":"apple"},
{"user":"jack","raw_id":"853","quantity":4,"ingredient_name":"peach"}
{"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"}
{"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}
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();

我尝试了你的解决方案,但groupBy出现了一个错误,我还需要“数量”。我尝试将您的groupBy更改为以下内容:groupBy('tB.card\u name','tA.username'),并添加了数量,但它为数量提供了null。另外,“have_quantity”显示的值不正确。将
COUNT(tA.have_quantity)have_quantity')
替换为
SUM(tA.have_quantity)as have_quantity')
以获得正确的
have_quantity
值。在你的问题中,我没有看到列名
card\u name
username
。在问题中添加正确的列名,以便更好地帮助您解决问题。哦,我指的是groupBy('tB.component\u name,tA.user')。这给了我一个错误,所以我将其更改为groupBy('tB.component_name','tA.user')。现在将其更改为SUM可以为have_quantity提供正确的值,但我仍然需要“quantity”,其结果为null@rotaercz如果将(非聚合)列添加到“选择”列表中,则可能还需要将其添加到“分组依据”列表中。否则,您可能会由于“按模式”仅显示“已满”组而出错。在您的情况下,它应该是
->groupBy('tB.component\u name,tA.user,tC.quantity')
。或者定义适当的唯一键,以便引擎可以确定功能依赖关系。当库存中有多行相同的成分名称时,quantity显示为null。当我尝试时,->groupBy('tB.component\u name','tA.user','tC.quantity')它显示的是库存的分解情况,这不是我想要的。你能写出你雄辩的模型关系吗?@G.baghasvili:我添加了Modelsquantity,当库存中有多行相同的成分时,它显示为null。\u name有没有办法使用一行在tC.quantity中有值的(因为始终只有一行具有值)而不是另一个显示为空的?我在问题中添加了表结构模型,如果有帮助的话。@rotaercz对此表示抱歉,
quantity
来自
tA=>my_inventory
,但应该来自
tC=>my_recipe
,更新了答案。它非常接近,但数量仍然显示为空。这只是得到一行。我不知道请输入所有对应的行。但是单行的值都是正确的。@rotaercz你能给我举个例子吗?在这个问题中,我有一个理想输出的例子。我只得到一行,而不是所有的行。