Php 如何将两个Laravel雄辩的查询转换为一个查询(因此我只访问了数据库一次,而不是两次)
假设我的数据库中有3个表 “我的食谱”、“我的清单”和“配料” “我的配方”表根据“配料”表和配方的“数量”需求存储原始id列表。“my_inventory”表存储原始id和“have_quantity”的列表 所以让我们看看我目前所拥有的东西。我有以下两个问题: 第一个问题: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')
$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你能给我举个例子吗?在这个问题中,我有一个理想输出的例子。我只得到一行,而不是所有的行。