2

レシピカテゴリ

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

レシピ名

id | recipe_name       | cid | iid
 1 | black forest cake | 1,2 | 1,2,3,4
 2 | angel cake        | 2   | 1,2,4
 3 | melting moments   | 3   | 2,5
 4 | croquembouche     | 1,3 | 1,5

材料

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

cid特定のレシピをプルするために使用してDBにクエリを実行できます。デザート:

SELECT * FROM recipe_name WHERE cid='1'

しかし、どうすれば材料がリストされている以下のような材料のリストを作成できます<br>か?

ブラックフォレストケーキ:
自家栽培小麦粉
ミルク
チョコレート
ベーキングパウダー

私はこれに慣れていないので、愚かな質問は許してください!

4

4 に答える 4

5

複数値の属性を単一のコンマ区切りフィールドに格納することは、ほとんどの場合、悪い考えです。すべてを照会するのが非常に困難になります。

代わりに、2つの新しい交差テーブルを使用してスキーマのリファクタリングを検討することをお勧めします。

これらの2つのテーブルはそのままです(交差テーブルと衝突しないように、の名前をに変更しただけです)recipe_categorycategories

CREATE TABLE categories (
   cid int NOT NULL PRIMARY KEY,
   category_name varchar(50)
) ENGINE=INNODB;

CREATE TABLE ingredients (
   iid int NOT NULL PRIMARY KEY,
   ingredient_name varchar(50)
) ENGINE=INNODB;

次のようにテーブルを変更し、フィールドとフィールドrecipe_nameを削除します。cidiid

CREATE TABLE recipe_name (
    id int NOT NULL PRIMARY KEY,
    recipe_name varchar(50)
) ENGINE=INNODB;

次に、次の2つの交差テーブルを使用して多値関係を定義できます。

CREATE TABLE recipe_ingredients (
    recipe_id int NOT NULL,
    ingredient_id int NOT NULL,
    PRIMARY KEY (recipe_id, ingredient_id),
    FOREIGN KEY (recipe_id) REFERENCES recipe_name (id),
    FOREIGN KEY (ingredient_id) REFERENCES ingredients (iid)
) ENGINE=INNODB;

CREATE TABLE recipe_categories (
    recipe_id int NOT NULL,
    category_id int NOT NULL,
    PRIMARY KEY (recipe_id, category_id),
    FOREIGN KEY (recipe_id) REFERENCES recipe_name (id),
    FOREIGN KEY (category_id) REFERENCES categories (cid)
) ENGINE=INNODB;

次に、これらのテーブルにサンプルデータを入力します。

INSERT INTO categories VALUES (1, 'desserts');
INSERT INTO categories VALUES (2, 'cakes');
INSERT INTO categories VALUES (3, 'biscuits');

INSERT INTO ingredients VALUES(1, 'self-raising flour');
INSERT INTO ingredients VALUES(2, 'milk');
INSERT INTO ingredients VALUES(3, 'chocolate');
INSERT INTO ingredients VALUES(4, 'baking powder');
INSERT INTO ingredients VALUES(5, 'plain flour');

INSERT INTO recipe_name VALUES(1, 'black forest cake');
INSERT INTO recipe_name VALUES(2, 'angel cake');
INSERT INTO recipe_name VALUES(3, 'melting moments');
INSERT INTO recipe_name VALUES(4, 'croquembouche'); 

レシピとその材料およびカテゴリとの関係を定義するには、次のように交差テーブルに入力する必要があります。

INSERT INTO recipe_categories VALUES (1, 1);
INSERT INTO recipe_categories VALUES (1, 2);
INSERT INTO recipe_categories VALUES (2, 2);
INSERT INTO recipe_categories VALUES (3, 3);
INSERT INTO recipe_categories VALUES (4, 1);
INSERT INTO recipe_categories VALUES (4, 3);

INSERT INTO recipe_ingredients VALUES (1, 1);
INSERT INTO recipe_ingredients VALUES (1, 2);
INSERT INTO recipe_ingredients VALUES (1, 3);
INSERT INTO recipe_ingredients VALUES (1, 4);
INSERT INTO recipe_ingredients VALUES (2, 1);
INSERT INTO recipe_ingredients VALUES (2, 2);
INSERT INTO recipe_ingredients VALUES (2, 3);
INSERT INTO recipe_ingredients VALUES (3, 2);
INSERT INTO recipe_ingredients VALUES (3, 5);
INSERT INTO recipe_ingredients VALUES (4, 1);
INSERT INTO recipe_ingredients VALUES (4, 5);

最後に、クエリの作成は次のように簡単になります。

SELECT i.ingredient_name
FROM   recipe_ingredients ri
JOIN   ingredients i ON (i.iid = ri.ingredient_id)
WHERE  ri.recipe_id = (SELECT id 
                       FROM   recipe_name 
                       WHERE  recipe_name = 'Black Forest Cake');

結果:

+--------------------+
| ingredient_name    |
+--------------------+
| self-raising flour |
| milk               |
| chocolate          |
| baking powder      |
+--------------------+
4 rows in set (0.00 sec)

<br>次に、SQLではなくアプリケーションコードでその結果セットをフォーマット(sを追加)することができます。

ただし、SQLでそれを本当に実行したい場合は、MySQLが便利なGROUP_CONCAT()関数をサポートしています。これは次のように使用できます。

SELECT GROUP_CONCAT(i.ingredient_name separator '<BR>') output
FROM   recipe_ingredients ri
JOIN   ingredients i ON (i.iid = ri.ingredient_id)
WHERE  ri.recipe_id = (SELECT id 
                       FROM   recipe_name 
                       WHERE  recipe_name = 'Black Forest Cake');

結果:

+----------------------------------------------------------+
| output                                                   |
+----------------------------------------------------------+
| self-raising flour<BR>milk<BR>chocolate<BR>baking powder |
+----------------------------------------------------------+
1 row in set (0.00 sec)

それをHTMLにダンプすれば、準備は完了です。

于 2010-07-19T01:48:46.217 に答える
1

まず、交差テーブルを使用する必要があります。この表には、recipe_namesのキーのリストと各材料のキーがあります。したがって、黒い森のケーキの場合、交差するテーブルに4つの行があります。これにより、クエリをより迅速かつ簡単に作成できます。キー配列をいじくり回す必要はありません。

黒い森のケーキのテーブルは次のようになります。

recipe_name_id  ingredients_id
1                 1
1                 2
1                 3
1                 4

クエリは次のようになります。

SELECT ingredient_name
  FROM recipe_name
     , ingredients
     , recipe_ingredients --intersect table
 WHERE recipe_name.id=1
   AND recipe_name.id = recipe_ingredients.recipe_name_id
   AND ingredients.id = recipe_ingredients.ingredients_id
于 2010-07-19T01:47:23.783 に答える
1

で行ったように、外部キーのコンマ区切りのリストは絶対に必要cidありません。代わりに、これらの関係を処理するだけのテーブルを作成します。iidrecipe_name

レシピ名

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

レシピカテゴリ

id | cid
 1 |  1
 1 |  2
 2 |  2
 3 |  3
 4 |  1
 4 |  3

レシピ成分

id | iid
 1 |  1
 1 |  2
 1 |  3
 1 |  4
 2 |  1
 2 |  2
 2 |  4
 3 |  2
 3 |  5
 4 |  1
 4 |  5

cid 1,2これで、デザートを選択するためのクエリ(たとえば、の行が欠落するため、古いものは機能しませんでした)は次のようになります。

SELECT recipe_name.* FROM recipe_name, recipe_categories WHERE recipe_name.id = recipe_categories.id AND recipe_categories=cid = 1;

それが済んだら、テーブルingredientsrecipe_ingredientsテーブルを結合するクエリを記述して、必要な結果を得ることができます。

SELECT ingredients.* FROM ingredients, recipe_ingredients WHERE recipe_ingredients.id = 1 AND recipe_ingredients.iid = ingredients.iid;
于 2010-07-19T01:52:48.520 に答える
0

あなたが質問しているという事実は、あなたが<br>これらをウェブページに表示したいということを私に告げています。私のアドバイスは、データのクエリと表示を分離することです。

レシピには多くの材料が含まれている可能性があり、材料は多くのレシピに表示される可能性があるため、レシピと材料の間に多対多の結合テーブルが必要になります。2つの列があります。1つはレシピの主キー用で、もう1つは材料の主キー用です。

カンマ区切りの値は、正規化ルールに違反します。あなたはそれらが何であるかを知りたいでしょう。

于 2010-07-19T01:48:37.357 に答える