以下の「Ticket[Number]」は、「選択された宝くじ番号のセット」を意味します。Set(a,b,c)
に等しいことを思い出してくださいSet(c,b,a)
。
私は次のようにします:
Purchase
-PersonID // associate Person (one person can have many purchases)
-TicketID // associate Ticket (a purchase is for one "ticket",
// which can be purchased many times)
-DisplayTicketNumber // for Human Display
Ticket
-TicketNumber
あれは、Purchase:M-1:Ticket
はDisplayTicketNumber
ユーザーが選択した数字、たとえば「3,1,2」です。一方、TicketNumber
は正規化されたチケット番号で、小さい値が最初に配置されます。最終的な形はこのようにmin,..,max
または類似しています。つまりDisplayTicketNumbers
、同じ値のセットを持つ任意の数 (任意の順序で) は同じになりTicketNumber
ます:
DisplayTicketNumber TicketNumber
1,2,3 1,2,3
2,3,1 1,2,3
3,2,1 1,2,3
3,2,1,4 1,2,3,4 .. and etc
次に、インデックスをTicketNumber
配置して、シンプルなものWHERE TicketNumber = @normalizedTicketNumber
が非常に高速なインデックスになるようにします。
実際、これは許容できる正規化された設計であり、TicketNumber (ラッフル番号など) がキーを形成すると主張します。したがって、これに対する私の議論は次のとおりです。
TicketNumber は、(ラッフルごとに) チケットを一意に識別する不透明な値です。DB モデル内の「詳細を知る」必要はありません。(場合によっては必要になるかもしれませんが、ここではありません。)
DisplayTicketNumber はユーザー入力のアーティファクトです。ただし、複数の DisplayTicketNumbers で同じ TicketNumber を表すことができます。これは「重複」の可能性を表していますが、これは選択された数値のリスト(セットよりも多くの情報を持つ) を表すFriendly Display値であることを理解することが重要です。
このような場合、DisplayTicketNumber
(and TicketNumber
) をトリガーで不変にして、作成後にデータベースの不整合が発生しないようにします。
FK を計算できる場合は、DisplayTicketNumber と TicketNumber の間の制約を不変性なしで適用できます。
(ラッフルごとに異なる TicketNumber を使用するなど、さまざまな詳細を省略しました。FK の も示していますが、それが許容される [非代理] キーであるTicketId
こともほのめかしています。)RaffleId,TicketNumber
また、Ticket テーブルを削除することもできます。宝くじ番号セットが共有されることはほとんどないため、関連する追加のチケット情報がない場合は、それを削除することで非正規化が許容される可能性があります。これの利点の 1 つは、テーブルTicketNumber
に移動してから、Ticket 値を正規化した計算列(まだインデックスが作成されている) に変換できることです。Purchase
また、MySQL が FK での計算列の使用を許可している場合、リレーションシップ-PK(Ticket.TicketNumber)
>を使用するとFK(Purchase.TicketNumber)
、Purchase.TicketNumber
が計算され、Ticket テーブルを削除せずにモデルの整合性を高めることができます。(ただし、MySQL を使用していないため、これが実行可能かどうかはわかりません。)
ハッピーコーディング。