2011-04-07 20 views
2

さまざまな数のユーザー設定を保存する必要があります。たとえば、映画について話している場合、ユーザー1は映画[A、B、C]を好きであり、ユーザー2は[C、D]を好きです。 テーブルにこれらを適切に保存するにはどうすればよいですか?好みの新しいタイプがある場合に効率的にこれらの設定を検索することができ、などのテーブルの多数を持っていない可変数の設定を保存する最も良い方法は?

+2

2つの要件は互いに反対です。 「適切に」とは正規化されたものを意味し、「新しいタイプの嗜好がある場合はテーブルの数が多い」という意味です。それを正しくやりたいのか、それとも簡単なのかを選んでください。 – JNK

答えて

6

ユーザー映画と第三表(好み)どこで一つのテーブルで一つのテーブルを持っていますユーザーをムービーにマッピングします。このように、ユーザーは複数のムービーが好きであり、異なるユーザーは同じムービーが好きです。その基本的なM:Nの関係。これはあなたが探しているものですか?

+0

しかし、これは、新しい環境設定がある場合、テーブルを多数持たないという要件には従いません。 – ChickenMilkBomb

+2

OPが新しいテーブルを作成するかどうかにかかわらず、これは正解です。 – JNK

0

スパースカラム!その彼らがために作られたまさに:

http://www.kodyaz.com/articles/sql-server-2008-sparse-columns.aspx

+0

リストのコンマ区切り文字列を提案していますか?または、各ユーザーに各映画のフィールドがあることを提案していますか?いずれにせよ、これは悪い解決策です。 – JNK

+0

それは好みの数によって異なります。設定が無制限であれば、それは悪いです。そうでなければ、EAVよりもはるかに効率的です – ChickenMilkBomb

0

あなたは好みの可変数を含む、種類のルックアップテーブルを作成してもらえますか?

新しいプリファレンスが作成されると、対応するIDを持つ表に入れられます。

は、その後、私はあなたがEntity-Attribute-Value modelに見てください

UserID 
PreferenceID 
3

で(多くの多くの)結合テーブルを作成します。
これは、論理スキーマの変更およびカーディナリティに関する大きな柔軟性を提供します。
さまざまなEAV実装と詳細については、stackoverflow postingsで説明していますが、this oneで始まる可能性があります

たとえば、アプリケーションが進化し、追加の種類の設定が必要な場合、物理スキーマ(サポートSQLテーブル)をまったく変更する必要はなく、新しい設定が属性テーブルのエントリになります。

EAVモデルの主な欠点は、やや複雑なテーブル構造と効率の低下です(たとえば、百万以上のエンティティ)。
単純なリレーショナル・モデルでは、データ・モデルはデータベース[物理]スキーマでより簡単に明らかです。 Leの効率の低下は、主に、値テーブルが一度に1つの属性値しか格納しない(結合インデックスの作成などを防止する)ため、同じ値を格納するために必要なレコード数単純なリレーショナル形式のデータ。

編集(パフォーマンスに関する)
私はダースと各/ほとんどが平均的に属性を最大4万行のデータインスタンスと比較的成功してきました。正確な「マイレージ」は、データの希薄さや属性値の相対的な選択性によって異なります。さらに、実装を複雑のコストでパフォーマンスを向上させるいくつかの「貿易のトリック」、があります。

  • 最も一般的に共有し、白羽-値を格納するには、エンティティテーブル内ではなく(またはに加えて属性)Valuesテーブル。
  • 複数の値テーブルを使用します。このような「パーティション」は、データ型、属性IDの範囲...
+0

これは小さな店舗には合っていますが、大きくなるにつれて悪夢になります – ChickenMilkBomb

+1

EAVはカジュアルなユーザーをデータベースデザイナーに変えます。あなたはそれをする前に懸命に考えてみたいです。 –

1
-- Predicate: User has id number :user_id. 
create table users (
    user_id integer primary key 
); 

-- Predicate: Movie has id number :movie_id and name :movie_name. 
create table movies (
    movie_id integer primary key, 
    movie_name varchar(150) not null -- Movie names aren't unique. 
); 

-- Predicate: User :user_id likes to watch movie :movie_id. 
create table movie_preferences (
    user_id integer references users (user_id), 
    movie_id integer references movies (movie_id), 
    primary key (user_id, movie_id) 
); 

後で好みの異なる種類を持っている場合は、たとえば、レストランでは、あなたはレストランのテーブル、およびレストランの好みのテーブルを必要としています。

-- Predicate: Restaurant has id number :restaurant_id and name :restaurant_name, 
-- and is known for its :known_cuisine cooking. 
create table restaurants (
    restaurant_id integer primary key, 
    restaurant_name varchar(150) not null, 
    known_cuisine varchar(30) not null 
); 

-- Predicate: User :user_id likes to eat at restaurant :restaurant_id. 
create table restaurant_preferences (
    user_id integer references users (user_id), 
    restaurant_id integer references restaurants (restaurant_id), 
    primary key (user_id, restaurant_id) 
); 

映画はレストランと同じものではありませんので、あなたは、追加の好みのための追加のテーブルを必要とし、同じことを意味するものではありません「私はバーガーキングが好きなの。」「私は 『トップガン』が好き」

テーブルは多数ありません。あなたは好みごとに一つのテーブルしか持っていません。 (最初にレストランを特定できるようにするためにはレストランのテーブルを実装する必要がありますから)

関連する問題