1

以下のようなMySQLの製品のテーブルをリファクタリングして正規化しようとしています:

CREATE TABLE `products` (
`id` varchar(45) NOT NULL, # alphanumeric product codes
`productCategory` varchar(45) NOT NULL, 
`productSubCategory` varchar(45) DEFAULT NULL, 
`productRange` varchar(45) NOT NULL,
`productClass` varchar(45) DEFAULT NULL,
`name` text NOT NULL,
`size` int(11) NOT NULL,
`sizeMeasure` varchar(5) NOT NULL,
`boxQuantity` int(11) NOT NULL,
`sellingPrice` double NOT NULL,
`rrp` double DEFAULT NULL,
`ordinalValue` int(11) NOT NULL,
PRIMARY KEY (`id`)
)

リファクタリングする必要があると私が信じているのは、productCategoryproductSubCategory、およびproductRangeフィールドです。これは、カテゴリの階層構造を取得できるようにする必要があるためです。また、カテゴリにメタデータを追加する予定です。

現在、テーブル フィールドには次のようなデータが含まれています。

productCategory     productSubCategory      productRange
---------------------------------------------------------
retail              retail_solution1        retail_solution1_range1
retail              retail_solution2        retail_solution2_range2
retail              retail_solution3        retail_solution3_range3
professional        prof_solution1          prof_solution1_range1
professional        prof_solution1          prof_solution1_range2
professional        prof_solution1          prof_solution1_range3
professional        prof_solution2          prof_solution2_range1
professional        prof_solution2          prof_solution2_range2
professional        prof_solution2          prof_solution2_range3
...                 ...                     ...

基本的に、productCategoryRETAIL セット内では、 フィールドproductSubCategoryproductRangeフィールドは同じVARCHAR(45)値を持ちます。

このツリーの深さが将来変わる可能性はほとんどありません。最も一般的な変更は、カテゴリ名に対して行われる可能性があります。

隣接リストとネストされたセット モデルを調べたところ、どういうわけか、ネストされたセット モデルを使用する傾向が強くなりました。


ネストされたセットモデルのアプローチについてこれまでに私が持っているもの:

モデル

カテゴリの追加:

CREATE PROCEDURE `addCategory`(IN parent VARCHAR(45), IN child VARCHAR(45))
BEGIN
    SELECT @myLeft := lft FROM product_category

    WHERE name = parent LIMIT 1;

    UPDATE product_category SET rgt = rgt + 2 WHERE rgt > @myLeft;
    UPDATE product_category SET lft = lft + 2 WHERE lft > @myLeft;

    INSERT INTO product_category(name, lft, rgt) VALUES(child, @myLeft + 1, @myLeft + 2);
END

カテゴリの削除:

CREATE PROCEDURE `deleteCategory`(IN name VARCHAR(45))
BEGIN
    SELECT @myLeft := lft, @myRight := rgt, @myWidth := rgt - lft + 1
    FROM product_category
    WHERE name = name;

    DELETE FROM product_category WHERE lft BETWEEN @myLeft AND @myRight;

    UPDATE product_category SET rgt = rgt - @myWidth WHERE rgt > @myRight;
    UPDATE product_category SET lft = lft - @myWidth WHERE lft > @myRight;
END

ただし、ストアドプロシージャではなく、SQLをJava Webアプリに入れたいと思います。JDBCTemplateすべてのデータ アクセスにSpring を使用しています。これまでマルチステートメントクエリを使用したことがないため、これにどのようにアプローチするかは現時点ではよくわかりませんJDBCTemplate

理想的には、DBUnit を使用してデータ アクセス層もテストしたいと考えています。

このプロジェクトで私をうんざりさせているのは、どういうわけかトップレベルのカテゴリをもっと重要視する必要があると感じていることです. おそらく、RETAIL と PROFESSIONAL のトップ レベル カテゴリは、カテゴリではなく製品タイプにする必要がありますか?

ガイダンスをいただければ幸いです。ありがとう。

4

1 に答える 1

0

うーん、これは見栄えが悪いです。

まず、カテゴリ ID を使用して (varchar ではなく) 製品に格納する必要があります。次に、カテゴリ自体の単純な階層セットアップを使用します。

2 つのレベルしか持てない場合 (製品がルート カテゴリ自体、またはそのサブカテゴリの 1 つにある場合) 単純に次のようにします。

categoryID, name, parentId:
1, sports, NULL
2, Crossbows, 1
3, Golf, 1
4, Healthcare, NULL

ここで、スポーツとヘルスケアは「マスター」レベルであり、小売業と専門家がそうです。

より深い構造を持つことができれば、別のアプローチを使用することを検討します. mysqlで(オラクルにはこれに対して/のためにCONNECT BY PRIORコマンドがあります)

この場合、OS のようにフルパスを文字列 (root/subcat1/subcat2...) に格納します。これは、何かが更新されたときに何らかの形でスティッキーになる可能性がありますが、完全ではなく取得が非常に高速です。階層の再帰的な検索。

この取得の問題について説明した別のトピック結果が完全かどうかをテストする MySQL Looped Join の実行方法は? (コードが必要です)

カテゴリを ID に解決したら、特定の (かつ唯一の) ID を製品自体に外部キーとして保存するだけです。

于 2012-09-03T11:17:49.217 に答える