ユーザーが自分のページにウィジェットを追加できるWebアプリケーションを設計しています。現在、性質が異なる2種類のウィジェットしかないため、属性は異なりますが、どちらも商品の販売に使用されます。将来的には他のウィジェットが実装されることを期待しています。ユーザーはそれらのいずれかまたは両方を自分のページに追加するオプションがあり、ユーザーが追加したウィジェットを記録しておく必要があります。また、販売した商品ごとに、金融取引の領収書を生成して保存する必要があります。すべての販売は、どのウィジェットからのものでも同じなので、(ウィジェットタイプごとに1つのテーブルではなく、たとえばWidget1Sales、Widget2Salesなどではなく)販売テーブルを1つだけ保存したいと思います。また、他のウィジェットが開発されている可能性があるため、すべてのウィジェットの属性用の列を持つスパースウィジェットテーブルを作成しない方がよいでしょう。
これまでのところ、私は次のデザインを思いつきました:
したがって、ユーザーが自分のページに追加するウィジェットごとに、2つのクエリを作成する必要があります。1つは特定のウィジェットテーブル名を取得するため、もう1つ(おそらく動的クエリ)はウィジェット情報を取得するためです。製品についても同じことが言えます。特定のウィジェットで販売された各製品は、特定の製品テーブル名を取得するためのクエリと、製品情報を取得するための別のクエリを作成する必要があります。この配置は機能しているようですが、テーブル名を別のテーブルに格納することは私にはまったく間違っているように思えます...このロジックを実装できる他の方法はありますか?ある種のクラステーブルの継承を実装することを検討しましたが、その特定のユースケースでこれをどのように行うことができるか想像できません。
他の(ユーザー)テーブルにテーブル名を格納することは、構造メタデータとユーザーデータを並べて格納するインスタンスです。これにはさまざまな興味深い効果があり、それらの効果の中には、デザイナーにとって魅力的なものがあります。マイナス面はあまり目立ちません。
マイナス面はこれです。結局、SQLで多くのデータ管理を「手動」で行うことになるため、別の設計ではDBMSに代わる可能性があります。これにより、コードの保守が難しくなり、実行が遅くなります。
そうは言っても、私はこのスタントを何回か引き抜いたことを認めます。その結果は通常、選択を後悔しないように十分なものでした。
あなたのケースで起こっている2番目のものがあります。ウィジェットと製品の両方のタイプ1と2は、クラス/サブクラスモデリング(または、タイプ/サブタイプモデリングを好む場合)のケースです。オブジェクトモデリングでは、継承が困難のほとんどを処理するため、この種のことは単純で簡単です。リレーショナルモデリングではそうではありません。そのため、リレーショナルモデリングには継承のメカニズムはありません。 SQLの一部のバリアントには、継承をモデル化および実装しやすくする拡張機能があります。
ここDBA領域には、SQLテーブルにサブクラス(またはサブタイプ)を実装する方法の問題に要約される多くの問題があります。それらの質問のいくつかは、このタグの下にグループ化されています: サブタイプ 。 StackOverflowでは、さらに多くのそのような質問があり、役立つ可能性のある3つの設計手法に関連する3つのタグがあります。単一テーブル継承、クラステーブル継承、および共有主キーです。
デザインはクラステーブル継承デザインに似ていますが、サブクラスとクラス間のIS-A関係を実装するために共有主キーの代わりに埋め込みテーブル名を使用する点が異なります。共有主キーを使用して探索し、スーパークラステーブルを各サブクラスに結合して、各サブクラスのすべてのデータを収集するビューを作成することができます。あなたがこのように行きたいかどうかはわかりません。何百もの異なる製品タイプがあると、それはひどく扱いにくくなるかもしれません。
どういうわけか、私と同じような問題に悩んでいるような気がします...
DBモデルを確認することをお勧めします。私はそれが過度に設計されていて、スマートなリレーショナルではないという印象を持っています...
ウィジェットの外部キー関係<ウィジェット1; widget <widget2ウィジェットID xがある場合、このIDはウィジェット1またはウィジェット2にのみ存在し、両方には存在しません。一方、widget_typeを指す追加の外部キーをウィジェット1に作成できます。
またはさらに良い:widget_typeの列をウィジェットに含める場合、ウィジェットテーブルには、ウィジェット1またはウィジェット2であるかどうかの情報がすでにあるため、ウィジェットid_xのタイプはウィジェット1またはウィジェット2であり、それを探すテーブル。
同時に、製品タイプ1と製品タイプ2は非常によく似ています。唯一の違いは、製品タイプ2にはさらに2つのフィールドがあるため、これをnull可能にして、1つのテーブルproduct_typeを使用することです。ウィジェット1とウィジェット2についても同じですが、ウィジェット2にはウィジェット1よりも1つだけ多くのフィールドがあります。
id widgetType(1または2にできます)widgetName widgetDescription pageID
id widgetID attribute1 attribute2(nullable)
iD名説明価格の重み(null可能)image_url(null可能)widgetInstanceID
このようにして、6つのテーブルを3つに減らします。