2010-07-20 82 views
2

从我的查询yesterday继,我已调整了我的食谱数据库,如下所示:查询多个表

类别

cid | category_name 
1 | desserts 
2 | cakes 
3 | biscuits 

食谱

id | recipe_name 
1 | black forest cake 
2 | angel cake 
3 | melting moments 
4 | croquembouche 
5 | crepes suzette 

成分

iid | ingredient_name 
1 | self-raising flour 
2 | milk 
3 | chocolate 
4 | baking powder 
5 | plain flour 
6 | eggs 

recipe_categories

recipe_id | category_id 
    1  | 1 
    4  | 1 
    5  | 1 
    1  | 2 
    2  | 2 
    3  | 3 
    4  | 3 

recipe_ingredients

recipe_id | ingredient_id 
    1  | 1 
    2  | 1 
    4  | 1 
    1  | 2 
    2  | 2 
    3  | 2 
    5  | 2 
    1  | 3 
    2  | 3 
    1  | 4 
    3  | 5 
    4  | 5 

我的查询需要通过使用
的成分分开列出的成分类别(可能使用GROUP_CONCAT返回食谱(我.ingredient_name分离'
“)输出作为昨天建议的)。

因此,对于甜点的查询将输出:

black forest cake: 
self-raising flour 
milk 
chocolate 

croquembouche: 
self-raising flour 
plain flour 

crepes suzette: 
milk 
plain flour 

我知道我必须参加recipe_ingredients和配方和成分和搜索类别,但是我真的很挣扎在如何做到这一点。

回答

2

查询:

SELECT A.recipe_name, GROUP_CONCAT(ingredient_name) AS ingredient_names 
FROM recipes A 
LEFT JOIN recipe_ingredients B ON A.id = B.recipe_id 
LEFT JOIN ingredients C ON B.ingredient_id = C.iid 
LEFT JOIN recipe_categories D ON A.id = D.recipe_id 
LEFT JOIN categories E ON D.category_id = E.cid 
WHERE category_id = <serach_id> 
GROUP BY id 

结果:

+-------------------+-------------------------------------------------+ 
| recipe_name  | ingredient_names        | 
+-------------------+-------------------------------------------------+ 
| black forest cake | chocolate,baking powder,self-raising flour,milk | 
| angel cake  | self-raising flour,milk,chocolate    | 
| melting moments | milk,plain flour        | 
| croquembouche  | self-raising flour,plain flour     | 
| crepes suzette | milk           | 
+-------------------+-------------------------------------------------+ 

这里是你的要求使用GROUP_CONCAT。每种成分由,

+0

分隔。非常感谢! – circey 2010-07-20 05:17:19

0

我要把它留给你找出如何得当格式,但上手,你需要加入的成分和配方表一起,但搜索的类别(加入为好)。

我发现做后者最简单/最好的方法是使用IN子句(EXISTS也适用)。例如:

SELECT * 
FROM recipes 
LEFT OUTER JOIN recipe_ingredients ON recipe.recipe_id = recipe_ingredients.recipe_id 
WHERE recipes.id IN (SELECT recipe_categories.recipe_id 
        FROM categories 
        INNER JOIN recipe_categories ON categories.cid = recipe_categories.category_id 
        WHERE categories.category_name = @search_term) 

需要注意的是,除非你正在寻找只有一类,做直JOIN当配方中含有一个以上的匹配类别将产生多个行,所以IN/EXISTS是最好的。

1

我发现,你可以将它们分解的时间,一步意义的事情。

首先,让我们抓住我们的甜点。

SELECT categories.cid 
    FROM categories 
WHERE category_name = 'desserts' 

现在让我们通过在结果的左侧粘贴沙漠食谱来抓取所有食谱。对于类别中的每个匹配行,recipe_categories中可以有一个或多个匹配行。对于recipe_categories中的每个匹配行,配方中可以有一个或多个匹配的行。

SELECT categories.cid, recipes.recipe_name 
     FROM categories 
LEFT JOIN recipe_categories ON (recipe_categories.category_id = categories.cid) 
LEFT JOIN recipes ON (recipes.rid = recipe_categories.recipe_id) 
    WHERE category_name = 'desserts' 

最后,让我们把我们的成分附在左边。对于我们目前为止的每一个匹配行(我们现在都在食谱中),我们可以在recipe_ingredients中有一个或多个匹配,然后在配方中再次匹配一个或多个匹配。

SELECT recipes.recipe_name, ingredients.ingredient_name 
     FROM categories 
LEFT JOIN recipe_categories ON (recipe_categories.category_id = categories.cid) 
LEFT JOIN recipes ON (recipes.rid = recipe_categories.recipe_id) 
LEFT JOIN recipe_ingredients ON (recipe_ingredients.recipe_id = recipes.rid) 
LEFT JOIN ingredients ON (ingredients.iid = recipe_ingredients.ingredient_id) 
    WHERE category_name = 'desserts' 

到目前为止我还在吗?

现在,它已经晚了,我还没有测试过这个,但它应该返回你正在查找的数据。实际上,我可能完全使用错误的连接类型来正确完成此操作。我敢肯定,如果我错了,评论中有人会纠正我。

这是什么不会做的是返回数据格式如你所愿。让我们对查询进行最后一次迭代以添加一些id字段。

SELECT recipes.rid, recipes.recipe_name, ingredients.iid, ingredients.ingredient_name 
     FROM categories 
LEFT JOIN recipe_categories ON (recipe_categories.category_id = categories.cid) 
LEFT JOIN recipes ON (recipes.rid = recipe_categories.recipe_id) 
LEFT JOIN recipe_ingredients ON (recipe_ingredients.recipe_id = recipes.rid) 
LEFT JOIN ingredients ON (ingredients.iid = recipe_ingredients.ingredient_id) 
    WHERE category_name = 'desserts' 

让我们把数据收集到一个多维数组中。假设我们正在使用PDO。

$query = '...'; 
$sh = $db->prepare($query); 
$sh->execute(); 
$recipes = array(); 
while($row = $sh->fetch(PDO::FETCH_ASSOC)) { 
// For each row in the result set, check to see if we've looked at this recipe. 
    if(!array_key_exists($row['rid'], $recipes)) { 
    // If we haven't, let's initialize the row with the recipe name 
    // and a place to stick each ingredient. 
     $recipes[ $row['rid'] ] = array( 
      'recipe_name' => $row['recipe_name'], 
      'ingredients' => array() 
     ); 
    } 
// Place this ingredient with the proper recipe. 
    $recipes[ $row['rid'] ]['ingredients'][ $row['iid'] ] = $row['ingredient_name']; 
} 

结果应该是这样的:

array(
    1 => array(
     'recipe_name' => 'black forest cake', 
     'ingredients' => array(
      '1' => 'self-raising flour', 
      '2' => 'milk', 
      ... 
     ) 
    ) 
) 

从这个结构,你可以做你想做的。